。
系统调用是怎么工作的?
一般的,进程是不能访问内核的。它不能访问内核所占内存空间也不能调用内核函数。CPU硬件决定了这些(这就是为什么它被称作"保护模式")。系统调用是这些规则的一个例外。其原理是进程先用适当的值填充寄存器,然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。在Intel
CPU中,这个由中断0x80实现。硬件知道一旦你跳到这个位置,你就不是在限制模式下运行的用户,而是作为操作系统的内核--所以你就可以为所欲为。
进程可以跳转到的内核位置叫做sysem_call。这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。接着,就调用函数,等返回后,做一些系统检查,最后返回到进程(或到其他进程,如果这个进程时间用尽)。如果你希望读这段代码,它在<内核源码目录>/kernel/entry.S,Entry(system_call)的下一行。
如何使用系统调用?
先来看一个例子:
#include /*定义宏_syscall1*/ #include /*定义类型time_t*/ _syscall1(time_t,time,time_t *,tloc) /*宏,展开后得到time()函数的原型*/ main() { time_t the_time; the_time=time((time_t *)0); /*调用time系统调用*/ printf("The time is %ld ",the_time); } |
系统调用time返回从格林尼治时间1970年1月1日0:00开始到现在的秒数。
这是最标准的系统调用的形式,宏_syscall1()展开来得到一个函数原型,稍后我会作详细解释。但事实上,如果把程序改成下面的样子,程序也可以运行得同样的结果。
#include main() { time_t the_time; the_time=time((time_t *)0); /*调用time系统调用*/ printf("The time is %ld ",the_time); } |
这是因为在time.h中实际上已经用库函数的形式实现了time这个系统调用,替我们省掉了调用_syscall1宏展开得到函数原型这一步。
大多 |