系列文章目录
文章目录
一 理论基础
操作系统接口
消息处理机制
系统调用的实现
系统调用的过程如下:
-
应用程序调用库函数(API);
-
API 将系统调用号存入 EAX,然后通过中断调用使系统进入内核态;
-
内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用);
-
系统调用完成相应功能,将返回值存入 EAX,返回到中断处理函数;
-
中断处理函数返回到 API 中;
-
API 将 EAX 返回给应用程序。
1.以close函数的实现为例看看系统调用的实现
lib/close.c文件中的内容:
#define __LIBRARY__
#include <unistd.h>
/*这是一个宏 在上面那个头文件中有定义*/
_syscall1(int, close, int, fd)
宏展开之后,内容如下
int close(int fd)
{
long __res;
__asm__ volatile ("int $0x80"
: "=a" (__res)
: "0" (__NR_close),"b" ((long)(fd)));
/*将__NR_close存入EAX,将参数fd存入EBX,然后进行0x80中断调用*/
/*调用返回后,从EAX取出返回值,存入__res,在通过对返回值的判断决定返回API怎样的返回值*/
if (__res >= 0)
return (int) __res;
errno = -__res;
return -1;
}
__NR_close就是系统调用的编号,在include/unistd.h中定义。
所以,在添加我们的系统调用时,一定要修改unistd.h这个文件。在用户空间,也要添加对应的系统调用。
2.内核的中断处理
在内核初始化时,主函数(在 init/main.c 中,Linux 实验环境下是 main())调用了sched_init()初始化函数。
void sched_init(void)
{
// ……
set_system_gate