1. 首页
  2. 网络技术
  3. 网络基础
  4. JPEG标准的中文文档PDF

JPEG标准的中文文档PDF

上传者: 2024-07-19 15:08:56上传 PDF文件 27.27MB 热度 6次

15.4系统调用进程同内核交互是通过一组定义好的函数来进行的,这些函数称为系统调用。在讨论支持网络的系统调用之前,我们先来看看系统调用机制的本身。从进程到内核中的受保护的环境的转换是与机器和实现相关的。在下面的讨论中,我们使用Net/3在386上的实现来说明如何实现有关的操作。在BSD内核中,每一个系统调用均被编号,当进程执行一个系统调用时,硬件被配置成仅传送控制给一个内核函数。将标识系统调用的整数作为参数传给该内核函数。在386实现中,这个内核函数为syscall。利用系统调用的编号,syscall在表中找到请求的系统调用的sysent结构。表中的每一个单元均为一个sysent结构。


struct sysent {

    int sy_narg;     /* number of arguments */

    int (*sy_call)(); /* implementing function */

}; /* system call table entry */

表中有几个项是从sysent数组中来的,该数组是在kern/init_sysent.c中定义的。


struct sysent[] = {

    /* . . . */

    { 3, recvmsg },   /* 27 = recvmsg */

    { 3, sendmsg },   /* 28 = sendmsg */

    { 6, recvfrom },  /* 29 = recvfrom */

    { 3, accept },    /* 30 = accept */

    { 3, getpeername }, /* 31 = getpeername */

    { 3, getsockname }, /* 32 = getsockname */

    /* . . . */

};

recvmsg系统调用在系统调用表中的第27个项,它有两个参数,利用内核中的recvmsg函数实现。syscall将参数从调用进程复制到内核中,并且分配一个数组来保存系统调用的结果。然后,当系统调用执行完成后,syscall将结果返回给进程。syscall将控制交给与系统调用相对应的内核函数。在386实现中,调用有点像:


struct sysent *callp;

error = (*callp->sy_call)(p, args, rval);

这里指针callp指向相关的sysent结构;指针p则指向调用系统调用的进程表项;args作为参数传给系统调用,它是一个32 bit长的字数组;而rval则是一个用来保存系统调用的返回结果的数组,数组有两个元素,每个元素是一个32 bit长的字。当我们用“系统调用”这个词时,我们指的是被syscall调用的内核中的函数,而不是应用调用的进程中的函数。syscall期望系统调用函数(即sy_call指向的函数)在没有差错时返回0,否则返回非0的差错代码。如果没有差错出现,内核将rval中的值作为系统调用(应用调用的)的返回值传送给进程。如果有差错,syscall忽略rval中的值,并以与机器相关的方式返回差错代码给进程,使得进程能从外部变量errno中得到差错代码。应用调用的函数则返回-1或一个空指针表示应用应该查看errno获得差错信息。在386上的实现,设置进位比特(carry bit)来表示syscall的返回值是一个差错代码。进程中的系统调用残桩将差错代码赋给errno,并返回-1或空指针给应用。如果没有设置进位。

想深入了解如何在内核中添加系统调用吗?看看这个指南 Linux内核添加系统调用。还在好奇ReactOS是如何实现系统调用的吗?这里有一篇有趣的文章漫谈兼容内核之一ReactOS怎样实现系统调用。如果你对更详细的源码实现感兴趣,可以下载syscall_intercept系统调用拦截库源码来看看。

这些资源不仅帮助你更好地理解系统调用的机制,还能让你掌握在不同环境下的具体实现和应用。再也不用担心读不懂复杂的内核源码了,赶紧去看看吧!

用户评论