图说socket与系统调用代码架构

1.引言

正式开始之前,每个人心里都应该有一点逼数,就像下面这张图一样。

图说socket与系统调用代码架构_第1张图片

系统调用也是函数调用,系统函数也是函数代码。系统函数与普通函数唯一的不同在于,系统函数可以使用cpu体系结构指令集中的特权指令,如启动I/O设备指令、修改某些个特殊寄存器的指令,如程序状态寄存器PSW。既然系统调用也是函数调用,那么就要遵守函数调用的基本法。1.传参 2.调用 3.返回。在汇编代码中,在正式call一个函数之前,需要将相关寄存器的值设置好,然后再修改pc寄存器值指向函数。上图中的eax = 2,就是在准备参数,为中断服务程序提供参数。

中断与系统调用

为什么缺页中断,除0中断,I/O中断不用传参数,凭什么INT 80就要传参数?为了理解这个问题,我们还需要多一点逼数。

图说socket与系统调用代码架构_第2张图片

 

可以理解INT 80,这个中断处理程序和其他中断处理程序有一些不一样。INT 80这个中断处理程序,要比其他中断处理程序要复杂,作为一个转发中心,它需要更多信息来确定它该调用哪一个系统函数。至于问为什么要这样设计?当然是为了节约宝贵的指令位数,同时易于扩展。若每一个系统调用都要求在自己在中断向量表中有一席之地(共有190多个系统调用),试想为了表示这样的数INT x(x > 256),INT这条指令中的立即数位,是不是要增加呢?同时,系统若增加了新的系统调用,比如在linux随后版本系统中新增的epoll这个系统调用,我们只用修改系统调用表,在表中添上epoll这个表项,就可以方便的通过更改参数,来快捷的调用epoll,而不用从指令上做修改。

2.正题

在认真看完了上面的引言之后,虽然有了逼数明白了大概代码架构逻辑,但我们还有落地,我们仍处于空战状态,空对空打嘴炮的状态。所以要来一段源码,验证是否与上面所写框架一致。

linux-5.0.1/arch/x86/entry/syscalls/syscall_32.tbl,以下列出socket相关的系统调用接口,以及对应的系统调用号和内核的socket接口。

102 i386    socketcall      sys_socketcall          __ia32_compat_sys_socketcall
359 i386    socket          sys_socket          __ia32_sys_socket
360 i386    socketpair      sys_socketpair          __ia32_sys_socketpair
361 i386    bind            sys_bind            __ia32_sys_bind
//sys_socketcall片段
switch (call) {
   case SYS_SOCKET:
       err = __sys_socket(a0, a1, a[2]);
       break;
   case SYS_BIND:
       err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
       break;
   case SYS_CONNECT:
       err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
       break;
   case SYS_LISTEN:
       err = __sys_listen(a0, a1);
       break;
   case SYS_ACCEPT:
       err = __sys_accept4(a0, (struct sockaddr __user *)a1,
                   (int __user *)a[2], 0);
       break;
   case SYS_GETSOCKNAME:
       err =
           __sys_getsockname(a0, (struct sockaddr __user *)a1,
                     (int __user *)a[2]);
       break;
   case SYS_GETPEERNAME:

所以这两段代码在说什么呢。INT 80进入到sys_call这个函数,这个函数实现上是switch,如果在进入sys_call这个函数时,传入102,那么就会跳转到sys_sokcetcall这个函数中去,然后我们在sys_sokcetcall函数中又看到了switch函数。根据你进入到sys_sokcetcall函数所传入的参数,将调用不同的系统函数。
在这里一个有趣的地方是,sys_call函数中,是可以直达sys_bind,sys_socket这类函数的,为什么还要设计一个socketcall函数,来调用?为了让你能够准确理解文字和代码所表述的意思,我又画了张图。图说socket与系统调用代码架构_第3张图片

震惊,是谁丧尽天良写出这样的代码架构?居心何在?

你可能感兴趣的:(图说socket与系统调用代码架构)