Loading... 到这里,有了前面的铺垫,要说的东西不多,其实没必要单独写出来,但是系统调用毕竟还是比较重要的东西,所以这里还是单独说一下。 Linux 下的系统调用占用的是 0x80 号中断,通过 eax 来选择要调用的功能,我们维护一个函数指针数组,存储各个功能的函数指针,然后用一个简单的汇编函数就可以实现调用 ```cpp extern syscall_table section .text global syscall_handler syscall_handler: push 0 ; syscall has no errcode, thus push 0 push ds push es push fs push gs pushad ; save the context push 0x80 ; push the INT number (as IntExit poped this) push edx push ecx push ebx call [syscall_table + eax * 4] add esp, 12 mov [esp + 8 * 4], eax ; update the eax in the backup ; so eax can be the ret val jmp IntExit ``` 然后只要完成对应的系统调用即可。为了使调用简单,对于需要不同参数个数的系统调用提供类似于如下的宏来进行调用 ```cpp #define _syscall3(NUMBER, ARG1, ARG2, ARG3) \ ({ \ int retval; \ __asm__ volatile \ ( \ "int $0x80" : \ "=a" (retval) : \ "a" (NUMBER), "b" (ARG1), \ "c" (ARG2), "d" (ARG3) : \ "memory" \ ); \ retval; \ }) \ ``` 对于一个简单的系统调用 getpid() 暴露给用户态的函数定义即为 ```cpp size_t getpid() { return _syscall0(SYS_GETPID); } ``` 在函数指针数组即系统调用函数表中进行如下的初始化 ```cpp syscall_table[SYS_GETPID] = sys_getpid; ``` 并提供一个在内核函数 sys_getpid 来执行 getpid 的操作 ```cpp size_t sys_getpid() { return GetCurrentThreadPCB()->pid; } ``` 然后就只完成需要提供的系统调用函数即可。 最后修改:2021 年 06 月 14 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,那听听上面我喜欢的歌吧