系统调用与信号:从用户态到内核态的 Linux 核心机制详解
系统调用系统调用用户与内核之间的桥梁内核操作系统核心功能应用程序ios或main程序可以调用库函数再系统调用(printf)或调用完库函数直接给用户结果(strlen)也可以直接系统调用(write)文件操作的系统调用write是系统调用内核中数据不会经过缓冲区printf实质先把内容放到缓冲区缓冲区再把数据提交给内核即交给write系统函数write再打印到屏幕上头文件#includestdio.h #includestdlib.h #includestring.h #includefcntl.h//操作文件 #inlcudeunist.h//exit(0); 结束当前进程向文件中写入内容//O_CREAT表示创建文件 0600表示权限只写 int main() { int fdopen(file.txxt,O_CREAT|O_WRONLY,0600); //6表示属主自己可读可写后两0代表同组人和其他人无任何权限 if(fd-1) { printf(open err\n); exit(1); } write(fd,hello,5); close(fd); exit(0); }读取一个文件中的所有内容//开始前先移动目标文件到当前位置 int main() { int fd open(passwd,O_RDONLY);//只读打开 if( fd -1 ) { printf(open passwd err\n); exit(1);//错误退出 } char data[512] {0}; int n 0; while( (n read(fd,data,511)) 0 )//n读到了文件中的内容就不为0 { printf(%s,data); memset(data,0,512);//防止data中有残留数据 } close(fd); exit(0); }对于父子进程父进程先打开的文件fork后子进程也可以访问并且父子进程共享文件偏移量系统调用与库函数区别系统调用一旦执行会切换到内核态给内核指令内核执行内核中的代码用户此时处于阻塞状态等内核返回结果库函数在用户空间直接调函数入口地址直接执行系统调用如何从用户态切换到内核态Eax寄存器CPU中的一个硬件还有Ebx,Ecx等等很多寄存器都是用来存传进来的参数应用程序运行到这里产生一个可识别的中断遇到更高优先级的事件被阻止继续执行代码。用户态阻塞给内核传参数包括系统调用号等存到Eax寄存器中。后续内核读取寄存器中的系统调用号在系统调用表中识别对应系统函数打开相应文件返回文件下标fd的值给寄存器传到文件表中恢复应用程序的执行时内核就已经帮我们打开文件了从寄存器中把返回值文件描述符读给fd信号信号软中断即软件层面的中断举例2号信号终端中断SIGINT ctrlc3号信号退出进程ctrl\9号信号杀死进程不允许用signal改变相应方式只能按默认方式相应15号信号执行kill命令系统会默认发送的信号17号信号子进程结束默认给父进程发送的信号信号相应方式默认方式0SIG_DFL忽略1SIG_IGN自定义方式通过signal函数改变信号响应方式#includestdio.h #includestdlib.h #includeunistd.h #inclduestring.h #includesignal.h void sig_fun(int sig) { printf(sig%d\n,sig); } int main() { signal(SIGINT,sig_fun); while(1) { printf(hello\n); sleep(1); } return 0; }signal函数放到main最开始一开始就和系统达成约定如果有发送2号信号内核就调用sig_fun函数响应方式由默认改为自定义注意用户自身没有调用sig_fun函数而是将函数名作为参数传给signal由内核代替执行