内核态程序和用户态和内核态通信程序的区别

:转载时请以超链接形式标明文章原始出处和作者信息及本声明
1 用户一般的数据操作只能在用户态进行;要操作内核态数据,必须利用标准的接口实现。&&&有很多方法可以读取或者修改内核态的数据。&& 1.1 可以利用动态模块,向用户态一样操作核心态数据结构&& 1.2 可以利用标准的系统调用、添加的系统调用来操作核心态数据&& 1.3 利用procfs读取、写入核心态数据 [sysctl系统调用]&&&1.4 利用sysfs读取、写入核心态数据&&&1.5 利用seq_file接口操作核心态数据&[自己添加内核操作方法]&& 1.6&利用kprobe、jprobe、jretprobe调试技术操作核心态数据&& 1.7 利用netlink钩子函数操作核心态数据结构&& 1.8 利用访问设备文件的方式操作核心态数据结构&&&.....2&&内核态和用户态区别&& 内核态的出现源于保护模式,从本质上讲linux系统不相信用户、也不认为用户有能力能很好的利用os所提供& && 的强大的资源管理能力。为此OS运行在与用户隔离的空间中,运行级别为0,所有进程的内核态数据空间都是一样&& 的,因为那里跑的是操作系统的代码,执行基本的资源管理任务,线性地址空间位于oxc000 0000以上,&& 内存映射方式为:实际内存=线性内存-3G;用户态属于每个进程的私有空间[这也是进程间会有差别的原因],我&& 们一&般打交道使用的空间都是用户空间,用户空间的管理依靠于task_strut的mm内存管理单元,其将内存划分 && 为若干内存区域(vm_area_struct),然后依靠页表来管理这些上述的内存区域,用户空间是可以被内存交换换进换&&&出的,而内核空间显然不能被换出...3 内核态用户态交互的接口&& 1 中描述了大量的内核态交互方法,这好比linux系统的底层不同文件系统的访问[其在vfs层总是归结于同一系统&&&调用read和write操作]。内核数据交互也是类似,不过与fs访问正好相反,上面大量的交互方式都归结于下面两个&& 最基本的函数[copy_from_user和copy_to_user]。所以摁其咽喉,方能掌握本质,分析分析copy_from_user&& 函数4 copy_from_user()详解&&& 2.6.35.3内核版本4-1& arch/x86/include/asm/Uaccess_32.h& static inline unsigned long __must_check copy_from_user(void *to,&&&&&& const void __user *from,&&&&&& unsigned long n){&int sz = __compiletime_object_size(to);&& //宏定义
&if (likely(sz == -1 || sz &= n))&&n = _copy_from_user(to, from, n);&else&&copy_from_user_overflow();
&}解释:先判断内核空间to的空间是否满足拷贝数据n大小,不满足发出WARN(1, "Buffer overflow detected!\n");4-2 _copy_from_user(to,from,n)/**&* copy_from_user: - Copy a block of data from user space.&* @to:&& Destination address, in kernel space.&* @from: Source address, in user space.&* @n:&&& Number of bytes to copy.&*&* Context: User context only.& This function may sleep.&*&* Copy data from user space to kernel space.&*&* Returns number of bytes that could not be copied.&* On success, this will be zero.&*&* If some data could not be copied, this function will pad the copied&* data to the requested size using zero bytes.&*/unsigned long_copy_from_user(void *to, const void __user *from, unsigned long n){&if (access_ok(VERIFY_READ, from, n))&&n = __copy_from_user(to, from, n);&else&&memset(to, 0, n);&}解释:注释非常清楚,access_ok()检查用户空间合理性[不超过0xc000 0000],userspace映射问题后面在看4-3 __copy_from_user(to,from,n)& &arch/x86/include/asm/Uaccess_32.h/*&* An alternate version - __copy_from_user_inatomic() - may be called from&* atomic context and will fail rather than sleep.& In this case the&* uncopied bytes will *NOT* be padded with zeros.& See fs/filemap.h&* for explanation of why this is needed.&*/static __always_inline unsigned long__copy_from_user(void *to, const void __user *from, unsigned long n){&might_fault();&if (__builtin_constant_p(n)) {&&
&&switch (n) {&&case 1:&&&__get_user_size(*(u8 *)to, from, 1, ret, 1);&&&&&case 2:&&&__get_user_size(*(u16 *)to, from, 2, ret, 2);&&&&&case 4:&&&__get_user_size(*(u32 *)to, from, 4, ret, 4);&&&&&}&}&return __copy_from_user_ll(to, from, n);}解释:首先查看n是否为固定值1,2,4字节,如果是固定大小,则操作简单;否则调用通用拷贝函数,适合于大块传输4-4& __copy_from_user_ll(to, from, n)& /arch/x86/libunsigned long __copy_from_user_ll(void *to, const void __user *from,&&&&&unsigned long n){&if (movsl_is_ok(to, from, n))&&__copy_user_zeroing(to, from, n);&else&&n = __copy_user_zeroing_intel(to, from, n);&}解释:首先判断是否需要大规模数据拷贝,一般返回1注:linux采用AT&T编码方式,左边值为原操作数,右边值为目的操作数,与intel编码方式不同4-5 __copy_user_zeroing(to, from, size)&&&& &/arch/x86/lib& 进入copy的关键#define& __copy_user_zeroing(to, from, size)&&&&\do {&&&&&&&&&\&int __d0, __d1, __d2;&&&&&&\&__asm__ __volatile__(&&&&&&\&&&&&&&&&&&&&&&&&&& #注:以4字节做为成串传送的基本单位&&"&cmp& $7,%0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&& #比较size是否大于7,即判断是否需要成串传送,cmp中右为原操作数&&"&jbe& 1f\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #如果小于7,跳到1处,以单字节作为传送单位&&"&movl %1,%0\n"&&&&&\&&&&&&&&&&&&&&&&&#ecx=to地址,此时ecx大于7字节,需要把余8单字节传,其余串传ecx=n&&"&negl %0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #ecx取补码,&& 正数补码为自身&&"&andl $7,%0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#ecx=ecx%8,显然操作前ecx=n,且andl中右为原操作数&&"&subl %0,%3\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&#寄存器X-=ecx,ecx为模8取余,显然此时寄存器X=n - n%8&&"4:& movsb\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&#余8剩余字节按照字节拷贝,显然此时ecx为n模8取余的值&&"&movl %3,%0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&#ecx=该寄存器X值,X值应为n-n%8,movl中左为原操作数&&"&shrl $2,%0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #然后ecx=ecx/4,此时ecx为movsl的次数,shrl中右为原操作数&&"&andl $3,%3\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#该寄存器X=X%4,andl中右为原操作数&&"&.align 2,0x90\n"&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&& #&&"0:& movsl\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&#按照四字节倍数拷贝,每次拷贝4个字节,&& 此时ecx=n/4&&"&movl %3,%0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&& #ecx值设为n%4,&& 此时该寄存器X=n%4&&"1:& movsb\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&& #以单字节拷贝&&"2:\n"&&&&&&&\&&&&&&&&&&&&&& &&".section .fixup,\"ax\"\n"&&&&\&&"5:&addl %3,%0\n"&&\&&&#寄存器X值[n-n%8] + ecx值[n%8-已拷贝字节] --& &ecx,addl,subl中右为原操作数&&"&jmp 6f\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#跳转到后边标号6处,此时ecx显然为剩余拷贝的字节数&&"3:&lea 0(%3,%0,4),%0\n"&&&&\&&&&&&&&&&&&&&& #ecx=ecx*4+n%4,ecx=在出错时剩余拷贝的字节数 &&"6:&pushl %0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#ecx压入栈,待后面出错返回时使用&&"&pushl %%eax\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&& #eax寄存器压栈,用0填充内核剩余空间时用eax值填&&"&xorl %%eax,%%eax\n"&&&&\&&&&&&&&&&&&&&&&& #eax清0&&"& stosb\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #此时将内核剩余复制空间清0&&"&popl %%eax\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&& #恢复eax值&&"&popl %0\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#ecx=剩余未拷贝的字节数&&"&jmp 2b\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#跳到前面2标号处,即退出内存拷贝&&".previous\n"&&&&&&\&&&& &&".section __ex_table,\"a\"\n"&&&&\&&&&&&&&&&&&& #专用的异常地址表,用于拷贝过程中的异常恢复&&"&.align 4\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #4字节为单位对其&&"&.long 4b,5b\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #标号5 为标号4的异常处理程序地址&&"&.long 0b,3b\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#标号3 为标号0的异常处理程序地址&&"&.long 1b,6b\n"&&&&&\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#标号6 为标号1的异常处理程序地址&&".previous"&&&&&&\&&: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)&\&&: "3"(size), "0"(size), "1"(to), "2"(from)&&\&&: "memory");&&&&&&\} while (0)解释:1&变量& 绑定寄存器& 初始值 输出值&&& 0&&&&& ecx&&&&&&&&&& size&&&& size&& 1&&&&& edi&&&&&&&&&&& to指针& __do变量&&&2&&&&& esi&&&&&&&&&&&&from&&&&__d1变量&& 3&&&&& 寄存器&&&&&&&&size&&&&&__d2变量2 分析2-1& gnu的gcc和ld支持四个段:text段、data段、fixup段、__ex_table段。& fixup段用于异常发生后的恢复操作,和text段没有太大差别& __ex_tabel段用于异常地址表2-2在cpu进行访址的时候,内核空间和用户空间使用的都是线性地址,cpu在访址的过程中会自动完成从线性地址到物理地址的转换[用户态、内核态都得依靠进程页表完成转换],而合理的线性地址意味着:该线性地址位于该进程task_struct-&mm虚存空间的某一段vm_struct_mm中,而且建立线性地址到物理地址的映射,即线性地址对应内容在物理内存中。如果访存失败,有两种可能:该线性地址存在在进程虚存区间中,但是并未建立于物理内存的映射,有可能是交换出去,也有可能是刚申请到线性区间[内核是很会偷懒的],要依靠缺页异常去建立申请物理空间并建立映射;第2种可能是线性地址空间根本没有在进程虚存区间中,这样就会出现常见的坏指针,就会引发常见的段错误[也有可能由于访问了无权访问的空间造成保护异常]。如果坏指针问题发生在用户态,最严重的就是杀死进程[最常见的就是在打dota时候出现的大红X,然后dota程序结束],如果发生在内核态,整个系统可能崩溃[xp的蓝屏很可能就是这种原因形成的]。所以linux当然不会任由这种情况的发生,其措施如下:&& &linux内核对于可能发生问题的指令都会准备"修复地址",比如前面的fixup部分,而且遵循谁使用这些指令,谁负责修复工作的原则。比如前面的代码中,标号5即为标号4的修复指令,3为0,6为1的修复指令。在编译过程中,编译器会将5,4等的地址对应的存入struct exception_table_entry{unsigned long insn,fixup;}中。insn即可能为4的地址,而fixup可能为5的地址,如果4为坏地址[即该地址并未在虚存区间中],则在页面异常处理过程中,会转入bad_area处,如果发生在用户态直接杀死进程即可。如果发生在内核态,首先通过search_exception_table查找异常处理表exception_table。即找到某一个exception_table_entry,假设其insn=标号4地址,fixup=标号5地址.内核将发生:regs-&ip=fixup,即通过修改当前的内核地址,从而将内核从死亡的边缘拉回来,通过标号5地址处的修复工作从而全身而退。&& 欢迎探讨、交流!
引用地址:
访问统计:
| 作者:NICK 素材来源:用户态与内核态的切换与区别
内核态和用户态的区别当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核状态。此时处理器处于特权级最高的(0级)内核代码。当进程处于内核态时,执行的内核代码会使用当前的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户态。即此时处理器在特权级最低的用户代码中运行。当正在执行用户程序而突然中断时,此时用户程序也可以象征性地处于进程的内核态。因为中断处理程序将使用当前进程的内核态。内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然联系,intel cpu提供Ring0-Ring3三种级别运行模式,Ring0级别最高,Ring3级别最低。Linux使用了Ring3级别运行用户态。Ring0作为内核态,没有使用Ring1和Ring2.Ring3不能访问Ring0的地址空间,包括代码和数量。Linux进程的4GB空间,3G-4G部分大家是共享的,是内核态的地址空间,这里存放在整个内核代码和所有的内核模块,以及内核所维护的数据。用户运行一程序,该程序所创建的进程开始是运行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统会调用内核中的代码来完成操作,这时,必须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换Ring3,回到用户态。这样,用户态的程序就不能随意操作1内核地址空间,具有一定的安全保护作用。用户态和内核态的转换(1)用户态切换到内核态的3种方式a.系统调用这是用户进程主动要求切换到内核态的一种方式,用户进程通过系统调用申请操作系统提供的服务程序完成工作。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的ine 80h中断。b.异常当CPU在执行运行在用户态的程序时,发现了某些事件不可知的异常,这是会触发由当前运行进程切换到处理此异常的内核相关程序中,也就到了内核态,比如缺页异常。c.外围设备的中断当外围设备完成用户请求的操作之后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条将要执行的指令转而去执行中断信号的处理程序,如果先执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了有用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。具体的切换操作从出发方式看,可以在认为存在前述3种不同的类型,但是从最终实际完成由用户态到内核态的切换操作上来说,涉及的关键步骤是完全一样的,没有任何区别,都相当于执行了一个中断响应的过程,因为系统调用实际上最终是中断机制实现的,而异常和中断处理机制基本上是一样的,用户态切换到内核态的步骤主要包括:(1)从当前进程的描述符中提取其内核栈的ss0及esp0信息。(2)使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个过程也完成了由用户栈找到内核栈的切换过程,同时保存了被暂停执行的程序的下一条指令。(3)将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。
最新教程周点击榜
微信扫一扫内核态和用户态的区别
zz - vivi_wind - 博客园
posts - 37, comments - 4, trackbacks - 0, articles - 0
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。 内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然的联系, intel cpu提供Ring0-Ring3三种级别的运行模式,Ring0级别最高,Ring3最低。Linux使用了Ring3级别运行用户态,Ring0作为 内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部 分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。用户运行一个程序,该程序所创建的进程开始是运 行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必 须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能 随意操作内核地址空间,具有一定的安全保护作用。至于说保护模式,是说通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程的地址空间中的数据。
1. 用户态和内核态的概念区别
究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子:
void testfork(){
if(0 = = fork()){
printf(&create new process success!\n&);
printf(&testfork ok\n&);
void testfork(){
if(0 = = fork()){
printf(&create new process success!\n&);
printf(&testfork ok\n&);
这段代码很简单,从功能的角度来看,就是实际执行了一个fork(),生成一个新的进程,从逻辑的角度看,就是判断了如果fork()返回的是0则打印相关语句,然后函数最后再打印一句表示执行完整个testfork()函数。代码的执行逻辑和功能上看就是如此简单,一共四行代码,从上到下一句一句执行而已,完全看不出来哪里有体现出用户态和进程态的概念。
如果说前面两种是静态观察的角度看的话,我们还可以从动态的角度来看这段代码,即它被转换成CPU执行的指令后加载执行的过程,这时这段程序就是一个动态执行的指令序列。而究竟加载了哪些代码,如何加载就是和操作系统密切相关了。
熟悉Unix/Linux系统的人都知道,fork的工作实际上是以系统调用的方式完成相应功能的,具体的工作是由sys_fork负责实施。其实无论是不是Unix或者Linux,对于任何操作系统来说,创建一个新的进程都是属于核心功能,因为它要做很多底层细致地工作,消耗系统的物理资源,比如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录页表等等,这些显然不能随便让哪个程序就能去做,于是就自然引出特权级别的概念,显然,最关键性的权力必须由高特权级的程序来执行,这样才可以做到集中管理,减少有限资源的访问和使用冲突。
特权级显然是非常有效的管理和控制程序执行的手段,因此在硬件上对特权级做了很多支持,就Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有CPL、DPL和RPL,这里不再过多阐述。硬件已经提供了一套特权级使用的相关机制,软件自然就是好好利用的问题,这属于操作系统要做的事情,对于Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在0级特权级的指令具有了CPU能提供的最高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。
3)用户态和内核态
现在我们从特权级的调度来理解用户态和内核态就比较好理解了,当程序运行在3级特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运行在0级特权级上时,就可以称之为运行在内核态。
虽然用户态下和内核态下工作的程序有很多差别,但最重要的差别就在于特权级的不同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序,比如上面例子中的testfork()就不能直接调用sys_fork(),因为前者是工作在用户态,属于用户态程序,而sys_fork()是工作在内核态,属于内核态程序。
当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,比如testfork()最初运行在用户态进程下,当它调用fork()最终触发sys_fork()的执行时,就切换到了内核态。
2. 用户态和内核态的转换
1)用户态切换到内核态的3种方式
a. 系统调用
这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
c. 外围设备的中断
当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。
2)具体的切换操作
从触发方式上看,可以认为存在前述3种不同的类型,但是从最终实际完成由用户态到内核态的切换操作上来说,涉及的关键步骤是完全一致的,没有任何区别,都相当于执行了一个中断响应的过程,因为系统调用实际上最终是中断机制实现的,而异常和中断的处理机制基本上也是一致的,关于它们的具体区别这里不再赘述。关于中断处理机制的细节和步骤这里也不做过多分析,涉及到由用户态切换到内核态的步骤主要包括:
[1] 从当前进程的描述符中提取其内核栈的ss0及esp0信息。
[2] 使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个
过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一
[3] 将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始
执行中断处理程序,这时就转到了内核态的程序执行了。【求助】windbg调试如何判断某个线程运行在用户态还是内核态 - 看雪安全论坛
该主题: "【求助】windbg调试如何判断某个线程运行在用户态还是内核态" 因在一定的时间里没有任何回复而自动关闭。如果您还对该主题感兴趣或者想参与对此主题的讨论,请您重新发表一篇相关的新主题。
注册日期: Jun 2011
现金: 39 Kx
获感谢文章数:0获会员感谢数:0
, 10:04:28
【求助】windbg调试如何判断某个线程运行在用户态还是内核态
《格蠹汇编》中75页说道,“从上下文来看,这个线程正在执行用户态的代码”。
我有个疑问,每个线程存在两个堆栈,用户态栈和内核栈,在一般情况下,我们查看某个线程的上下文时,发现eip的地址都&0x8000000,个人的理解是,这个是用户态的栈,自然都在低2G内存运行。
而书中又说“大多数情况下,我们很难在调试器中看到一个线程在用户态执行,因为大多数应用程序的用户态代码都是执行一点操作后,便调用系统服务进入内核态执行。”
作者肯定不像我说的,是看eip的值,来判断线程是在用户态执行,那么怎么查看某个时刻,线程是在用户态运行还是内核态?
注册日期: Mar 2014
现金: 199 Kx
获感谢文章数:7获会员感谢数:34
, 12:51:00
注册日期: Jun 2011
现金: 39 Kx
获感谢文章数:0获会员感谢数:0
, 15:30:46
最初由 sidyhe发布
能不能再提示下
该主题: "【求助】windbg调试如何判断某个线程运行在用户态还是内核态" 因在一定的时间里没有任何回复而自动关闭。如果您还对该主题感兴趣或者想参与对此主题的讨论,请您重新发表一篇相关的新主题。
您不可以发表主题
您不可以回复帖子
您不可以上传附件
您不可以编辑自己的帖子
论坛论坛启用
用户控制面板
会员在线状态
CrackMe攻击篇,分析文章提交区
『看雪众测/众包』
『求助问答』
『经典问答』
『资料导航』
『软件调试逆向』
『密码学』
『编程技术』
『C32Asm』
『MDebug』
『安全工具开发』
『加壳与脱壳』
『CrackMe&ReverseMe』
『资源下载』
『Android 安全』
『Android 开发』
『iOS安全』
『WEB安全』
『漏洞分析』
『外文翻译』
『招聘专区』
『职业生涯』
『15PB培训』
『麦洛克菲培训』
『茶余饭后』
『安全资讯』
『论坛活动』
6)PEDIY Crackme竞赛2009
7)看雪十周年专版
8)腾讯公司2010软件安全竞赛
9)2011 Exploit Me竞赛
『图书项目版』
《加密与解密(第三版)》
《C++反汇编与逆向分析技术揭秘》
《Android软件安全与逆向分析》
『论坛版务』
所有时间均为北京时间, 现在的时间是 .
&&& 看雪学院()
| 提供带宽资源
|&微信公众帐号:程序由用户态改写成内核态遇到的问题,求帮助_linux吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:157,326贴子:
程序由用户态改写成内核态遇到的问题,求帮助收藏
这是一个gcm的加密测试程序,想要把它打包成内核模块加载到内核中,首先我把代码中该修改的地方都修改了,比如printk还有头文件之类的,然后修改makefile文件出现了问题。原来的makefile是这样的INCLUDE_DIRS := ../include ..INCLUDES := $(foreach i,$(INCLUDE_DIRS),-I $i)CC
:= gccCXXFLAGS := -g -D LINUX $(INCLUDES)LDFLAGS += -glib_objs := \aes128_cbc_dec_by4_sse.o \……这里是一些在上级的include目录下的文件,略去了……gcm_avx_gen2.o \gcm_avx_gen4.oOBJ := $(foreach i,$(lib_objs),../obj/$(i))gcm: main.o $(OBJ)$(CC) $(LDFLAGS) -o $@ main.o $(OBJ)main.o: main.c do_test.h$(CC) $(CXXFLAGS) -c $& -o $@clean:rm -f *.o *.cmd *.ko *.mod.c执行make命令,首先生成main.o,然后将上级目录下的include中的文件( OBJ 所代表的) 和main.o一块作为依赖,生成gcm可执行程序。。。——————————————————————————————————————————下面是我修改后的makefileINCLUDE_DIRS := ../include ..INCLUDES := $(foreach i,$(INCLUDE_DIRS),-I $i)lib_objs := \aes128_cbc_dec_by4_sse.o \……这里是一些在上级的include目录下的文件,略去了……gcm_avx_gen2.o \gcm_avx_gen4.oOBJ := $(foreach i,$(lib_objs),../obj/$(i))obj-m += gcm.ogcm-objs:= main.o do_test.h $(OBJ)main.o: main.c do_test.h$(CC) $(CXXFLAGS) -c $& -o $@KERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd) default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versionsrm -rf Module.* modules.* .PHONY: default clean问题出现了,如果去掉上面makefile中的main.o: main.c do_test.h$(CC) $(CXXFLAGS) -c $& -o $@这两句,那么就不会生成main.o,出现各种错误。我们知道内核模块编写执行make后首先应该进入系统的内核目录,可是如果不去掉这两句,系统就会先执行这两句,不会进入系统内核目录下,出现各种错误。而且这两句放到前面也是一样的。。。——————————————————————————————————————————————不知道有没有说清楚问题。总结起来就是:我们在内核模块编写的时候,makefile中一般都有obj-m := my_module.omy_module-objs := extern_app.o test_module.o这样的部分,可是如果上面的依赖extern_app.o或者test_module.o不能直接生成,而是需要你去写响应的语句才行,那么该怎么办?希望有朋友帮忙解惑
达内linux培训,将网络工程与Linux运维结合,培养高端 linux人才.达内linux培训,名师授课+百万机房+红帽认证;名企项目实战,13年20万学员成功就业!
可以这么改?
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或

我要回帖

更多关于 linux用户态和内核态 的文章

 

随机推荐