1. Linux系统调用实现机制Linux系统调用实现分为三个核心部分调用请求、响应请求和功能实现。整个流程通过软中断机制实现用户态到内核态的切换其基本工作原理如下应用程序通过特定接口发起系统调用请求CPU执行软中断指令(INT 0x80)进入内核态内核根据系统调用号执行对应的服务函数执行完成后返回用户态1.1 系统调用流程系统调用流程如下图所示文字描述应用程序 → 调用请求接口 → 软中断指令 → 中断服务程序 → 系统调用表 → 内核功能实现 → 返回用户态2. 调用请求实现方式系统调用提供了四种主要的调用请求方式每种方式最终都会触发软中断指令。2.1 glibc库函数方式glibc作为标准C库封装了大多数系统调用提供更友好的API接口。其实现特点包括#include stdio.h int main() { int rc chmod(./testfile, 0666); if(rc -1) perror(chmod fail); else printf(chmod succeed); return 0; }glibc与系统调用的对应关系有三种典型情况一对一映射如open()对应sys_open一对多映射如printf()会调用多个系统调用多对一映射如malloc()/free()都使用sys_brk2.2 syscall函数方式当glibc未封装特定系统调用时可直接使用syscall函数#include stdio.h #include unistd.h #include sys/syscall.h int main() { int rc syscall(SYS_chmod, ./testfile, 0777); if(rc -1) perror(SYS_chmod chmod fail); else printf(SYS_chmod chmod succeed); return 0; }2.3 _syscall宏方式Linux内核提供了一组宏用于直接定义系统调用接口#define _syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile (int $0x80 \ : a (__res) \ : 0 (__NR_##name)); \ if (__res 0) \ return (type) __res; \ errno -__res; \ return -1; \ }使用示例_syscall0(int, testcall);2.4 直接软中断方式最底层的方式是直接使用汇编指令触发中断#include stdio.h #include sys/syscall.h int main() { long rc; asm(int $0x80 : a (rc) : 0 (SYS_chmod), b ((long)./testfile), c ((long)0777)); if(rc -1) perror(SYS_chmod chmod fail); else printf(SYS_chmod chmod succeed); return 0; }3. 中断响应机制3.1 中断触发与处理当执行INT 0x80指令时处理器完成以下操作从用户模式切换到特权模式跳转到0x80中断向量对应的服务程序根据寄存器传递的参数执行相应功能中断向量在内核中的初始化set_system_trap_gate(SYSCALL_VECTOR, system_call);3.2 系统调用分发核心分发逻辑在entry_32.S中实现ENTRY(system_call) SAVE_ALL cmpl $(nr_syscalls), %eax jae syscall_badsys syscall_call: call *sys_call_table(,%eax,4) movl %eax,PT_EAX(%esp) ENDPROC(system_call)3.3 系统调用表sys_call_table是函数指针数组实现调用分发const sys_call_ptr_t sys_call_table[] { [0] sys_read, [1] sys_write, [2] sys_open, // ... };4. 功能实现机制4.1 系统调用实现模板内核使用SYSCALL_DEFINE宏定义系统调用SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) { return sys_fchmodat(AT_FDCWD, filename, mode); }宏展开后实际生成asmlinkage long sys_chmod(const char __user *filename, mode_t mode) { return sys_fchmodat(AT_FDCWD, filename, mode); }4.2 自定义系统调用实现添加自定义系统调用需要三个步骤定义用户空间接口_syscall0(int, weiweicall)添加系统调用号#define __NR_weiweicall 295 __SYSCALL(__NR_weiweicall, sys_weiweicall)实现内核函数SYSCALL_DEFINE0(weiweicall) { printk(weiwei system call!); return 1; }5. 系统调用分类Linux系统调用按功能可分为以下几大类5.1 进程控制类fork, clone, execvegetpid, getppidwait, waitpid5.2 文件操作类open, read, writestat, fstatmkdir, unlink5.3 系统控制类ioctl, rebootsysinfo, gettimeofday5.4 内存管理类brk, mmapmlock, mprotect5.5 网络管理类socket, bindsend, recv5.6 进程通信类pipe, shmgetmsgctl, semop