正文:

  1. 内核提供了用户进程与内核进行交互的一组接口,这些接口让应用程序受限地访问硬件设备,提供了创建新进程并与已有进程进行通信的机制,也提供了申请操作系统其他资源的能力。
  2. Linux的系统调用作为C库的一部分,C库实现了系统的主要API,包括标准C库函数和系统调用接口。
  3. 系统调用在出现错误的时候C库会把错误码写入errno全局变量。通过perror()库函数,可以把该变量翻译成用户可以理解的错误字符串。
  4. 函数声明中的asmlinkage限定词,是一个编译指令,通知编译器仅从栈中提取该函数参数。
  5. 在Linux中,每个系统调用被赋予一个系统调用号。当用户空间的进程执行一个系统调用的时候,这个系统调用号就用来指明到底是要执行哪个系统调用。进程不会提及体统调用的名称!
  6. 内核记录了系统调用表中所有已注册过的系统调用的列表,存储在sys_call_table中(arch//kernel/syscall.c)。
  7. 用户空间的程序无法直接执行内核代码。它们不能直接调用内核空间的函数,因为内核驻留在受保护的地址空间上。
  8. 系统调用处理程序实际上是一个异常处理程序,靠软中断实现的,它通过引发一个异常来促使系统切换到内核态去执行异常处理程序(系统调用处理程序system_call()),它与硬件体系结构紧密相关。
  9. 在陷入内核空间之前,用户空间进程得先把系统调用号放入相应体系结构CPU中相应的寄存器内,这样系统调用处理程序就可以读取系统调用号,转而去执行相应的程序。
  10. 内核在接收一个用户空间的指针之前,内核必须保证:指针指向的内存区属于用户空间;指针指向的内存在进程的地址空间里;如果是读,内存应该被标记为读,写和执行也如此.
  11. Linux本身提供了一组宏,用于直接对系统调用进行访问。它会设置好寄存器并调用陷入指令。这些宏是_syscalln(),其中n范围为0~6,代表给内核的参数个数。对于每个宏来说,都有2+2n个参数,第一个参数对应系统调用的返回值类型,第二个参数是系统调用的名称,后面的就是按照系统调用参数的顺序排列的每个参数的类型和名称。例如: #define NR_open 5 _syscall3(long,open,const char*,filename,int,flags,int,mode)