如何确定函数是否是内核/用户模式的一部分?

时间:2015-01-25 14:04:29

标签: c kernel user-mode-linux

如何检查函数是否属于内核或用户空间? (或者也可能都是)是否对所有内核库/函数有任何概述?

在Unix环境中使用C语言。

e.g。 rand()是纯用户空间,malloc()是用户和内核空间等。

手册页不包含任何信息。

3 个答案:

答案 0 :(得分:1)

This文章应该为您提供有关系统调用(进入内核空间)的一些信息。现在你可以使用这个粗略(并不是非常准确)的指导原则:

  1. 第2部分的所有手册页都是系统调用。

  2. 如果手册页来自第3部分,请查看底部的SEE ALSO部分以查看它是否使用第2部分中的任何命令。(可能还需要阅读手册页本身。)

  3. 同样,这不是很准确,但是如果没有阅读源代码,它应该会给你一个想法。

答案 1 :(得分:0)

在整个运行期间,一个进程计算了很多系统调用,甚至在它实际运行之前就开始了。

您可以选择调试这些选项:

  • 使用调试信息编译您自己的glibc
  • strace
  • gdb

第三个选项可能是最好的选项,特别是如果您只对一个函数而不是一组函数感兴趣(其中strace会更好)。实际上,gdb允许您捕获附加进程或某些特定进程发出的系统调用;您可以使用catch syscall 数字catch syscall获取此信息,以便全部捕获。

您可能还希望通过使用-static编译代码来避免动态链接器在运行时进行的调用。

答案 2 :(得分:0)

取决于你所谓的“内核模式”功能。如果我理解你是正确的,那么你的意思是某些C函数要求做一些事情,比如malloc()调用brk(),所以内核会增加进程堆大小。

所以你需要的是检测哪些函数通常通过调用系统调用(如brk()来完成)从内核中提问。

现在是时候确定哪些函数调用哪个系统调用了。有两种方法可以做到这一点:

  • 静态代码分析。只需构建一个glibc的调用图,然后绘制根是系统调用的图形。唯一的问题是glibc的复杂性,因此很难构建整个callgraph。
  • 动态代码分析。将调试器/跟踪器附加到进程,当进程调用系统调用时,打印其堆栈。这种方法并不涵盖所有功能和案例,但易于实施。

即。使用gdb:

myaut@panther:~> gdb /bin/cat
...
(gdb) b brk
Function "brk" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
(gdb) commands 1
> bt
> cont
> end
(gdb) r
Starting program: /bin/cat 

...

Breakpoint 1, __brk (addr=0x62d000) at ../sysdeps/unix/sysv/linux/x86_64/brk.c:28
28      in ../sysdeps/unix/sysv/linux/x86_64/brk.c
#0  __brk (addr=0x62d000) at ../sysdeps/unix/sysv/linux/x86_64/brk.c:28
#1  0x00007ffff7b0eea5 in __GI___sbrk (increment=135168) at sbrk.c:53
#2  0x00007ffff7aaeda9 in __GI___default_morecore (increment=<optimized out>) at morecore.c:48
#3  0x00007ffff7aaaa37 in sysmalloc (av=0x7ffff7dd5640 <main_arena>, nb=32) at malloc.c:2454
#4  _int_malloc (av=0x7ffff7dd5640 <main_arena>, bytes=5) at malloc.c:3718
#5  0x00007ffff7aac263 in __GI___libc_malloc (bytes=5) at malloc.c:2859
...
#10 0x0000000000401d8a in main (argc=1, argv=0x7fffffffdd08) at cat.c:563

或者某些动态跟踪引擎,例如SystemTap(Linux):

# stap -e '
        probe syscall.brk { 
            if(pid() == target()) 
                print_ubacktrace(); 
        } ' -c /bin/cat -d /lib/x86_64-linux-gnu/libc.so.6
...
0x7f5edb427ffa : brk+0xa/0x70 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb4280ad : sbrk+0x4d/0xb0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3d0ae9 : __default_morecore+0x9/0xb0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3cd1e6 : malloc_trim+0x15e6/0x23c0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3cec00 : malloc+0x70/0x340 [/lib/x86_64-linux-gnu/libc-2.13.so]
...
0x401bea [/bin/cat+0x1bea/0xc000]

或DTrace:

root@sol11:~# dtrace -n '
            syscall::brk:entry 
            /pid == $target/ { 
                ustack() 
            }' -c '/bin/cat'
CPU     ID                    FUNCTION:NAME
0     58                        brk:entry 
            libc.so.1`_brk_unlocked+0x15
            libc.so.1`sbrk+0x38
            ...
            libc.so.1`malloc+0x38
            libc.so.1`strdup+0x29
            libc.so.1`expand_locale_name+0x333
            libc.so.1`setlocale+0x89c
            cat`main+0x23
            cat`_start+0x7d