读取之后会发生什么情况是为Linux套接字调用的

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

n = read(fd, buf, try_read_size); 

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

我想这可能会最终调用一个系统调用内核。 但任何人都可以提供一些细节? 在glibc或内核源代码中说源代码的实现?

Solutions Collecting From Web of "读取之后会发生什么情况是为Linux套接字调用的"

从高层角度来看,这是发生了什么事情:

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