arm64大约支持280个系统调用,我们平时使用的这些系统调用,到底工作原理是什么,调用后又是到哪里实现的呢,这篇文章初步了解下内核系统调用的流程,并告诉跟踪这个流程的方法。
图片
废话不多说,如上就是linux的系统调用关系图:
1.绝大部分用户态系统调用接口,都经过glibc库,最终到内核是sys_xx实现函数完成功能并返回用户态;
2.少量glibc不支持的API可通过其他方式直接到内核sys_xx实现函数完成功能并返回用户态;
3.存在少量系统调用glibc内部实现,但是实现流程使用内核关键函数,比如malloc;
举例说明如何跟踪
open()函数
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
open("xx", O_CREAT);
}
以上是open的系统调用,可以使用gcc open.c -o open命令编译成二进制。
ldd open
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f53081a5000)
从上可知最终到系统libc库
查看libc库的open:
nm -D /lib/x86_64-linux-gnu/libc.so.6 |grep open
00000000000f7030 W open
00000000000f7030 W __open
接下来需要下载glibc库的源码,然后
git checkout glibc-2.9
vim io/open.c
int
__open (file, oflag)
const char *file;
int oflag;
{
int mode;
if (file == NULL)
{
__set_errno (EINVAL);
return -1;
}
if (oflag & O_CREAT)
{
va_list arg;
va_start(arg, oflag);
mode = va_arg(arg, int);
va_end(arg);
}
__set_errno (ENOSYS);
return -1;
}
如何glibc库经过初步的参数检查,会调用到内核的系统调用sys_open() ->include/linux/syscalls.h ->sys_open -> do_sys_open ->fs/open.c ->long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
系统调用 malloc
cat test.c
#include <stdio.h>
#include <malloc.h>
void main()
{
void *c = (void*)malloc(10);
free(c);
}
如上
ldd test
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f53081a5000)
nm -D /lib/x86_64-linux-gnu/libc.so.6 |grep malloc
0000000000084130 T __libc_malloc
0000000000084130 T malloc
glibc源码中
find . -name malloc.c
./malloc/malloc.c