读取后发生的事情是为Linux套接字调用的

时间:2012-04-19 10:36:22

标签: linux sockets networking

调用read后实际发生了什么:

n = read(fd, buf, try_read_size);

这里fd是TCP套接字描述符。 buf是缓冲区。 try_read_size是程序尝试读取的字节数。

我想这可能最终会调用对内核的系统调用。但是有人能提供一些细节吗?说glibc或内核源代码中的源代码实现?

1 个答案:

答案 0 :(得分:4)

从高层来看,这就是:

  • glibc提供的包装函数叫做
  • 包装器函数将在堆栈上传递的参数放入寄存器,并在专用于此目的的寄存器中设置系统调用号(例如x86上的EAX)
  • 包装函数执行陷阱或等效指令(例如SYSENTER)
  • CPU切换到ring0,并调用陷阱处理程序
  • 陷阱处理程序检查系统调用号的有效性,并在跳转表中查找内核函数
  • 相应的内核函数检查参数是否有效(例如,范围bufbuf+try_read_size是指可访问的内存页,fd实际上是文件描述符)。如果出现问题,则会生成负错误代码(例如-EFAULT),cpu将切换回用户模式,并且调用将返回到包装器。
  • 根据文件描述符的类型调用另一个函数(在您的情况下是一个套接字,但是可以从块设备或proc条目读取或更具异国情调的内容)
  • 检查套接字的输入缓冲区:
    • 如果在缓冲器中的一些数据,min(available, try_read_size)被复制到buf,所述量被写入到返回码寄存器(EAX在x86)时,CPU切换回用户模式和调用返回包装器。
    • 如果输入缓冲区为空
      • 如果连接已关闭,则将零写入返回码寄存器,cpu将切换回用户模式,并且调用将返回到包装器
      • 如果连接已关闭
        • 如果套接字是非阻塞的,则将错误代码(-EAGAIN)写入返回代码寄存器,cpu将切换回用户模式,并且调用将返回到包装器。
        • 如果套接字非阻止
        • ,则暂停该过程
  • 包装函数检查返回值是否为负(错误)。
    • 如果为正或零,则返回值。
    • 如果为负数,则将errno设置为否定值(报告错误)并返回-1