linux - 为 Linux 套接字调用读取后会发生什么

标签 linux sockets networking

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

n = read(fd, buf, try_read_size);

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

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

最佳答案

从高层次的角度来看,这就是发生的事情:

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

关于linux - 为 Linux 套接字调用读取后会发生什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10226294/

相关文章:

linux - 显示包含在 elf 文件中的字符串

c - recvfrom 在信号后不返回-1

Java并发,在父线程中访问socket

c - 在c中使用windows套接字应用程序绑定(bind)错误10038

c - C 语言的 REST 客户端

c - 使用 winHttpApi 或套接字发送大文件是否明智?

java - 检查网页的状态

linux - bash 中的简单正则表达式解析

c - setitimer 的 ITIMER_PROF(SIGPROF) 是否发送到多线程和 NPTL 以及 Linux(2.6.21.7) 中的每个线程?

java - 在linux命令上打开2个jar文件