Linux套接字调用读取后会发生什么 [英] what happens after read is called for a Linux socket
本文介绍了Linux套接字调用读取后会发生什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
调用read之后实际发生的事情:
What actually happens after calling read:
n = read(fd, buf, try_read_size);
此处fd是TCP套接字描述符.buf是缓冲区.try_read_size是程序尝试读取的字节数.
here fd is a TCP socket descriptor. buf is the buffer. try_read_size is the number of bytes that the program tries to read.
我想这可能最终会调用对内核的系统调用.但是有人可以提供一些细节吗?说glibc还是内核源代码中的源代码实现?
I guess this may finally invokes a system call to the kernel. But could anyone provide some details? say the source code implementation in glibc or kernel source?
推荐答案
从高层的角度来看,会发生以下情况:
From a high-level perspective, this is what happens:
- 由glibc提供的包装器函数称为
- wrapper函数将在堆栈上传递的参数放入寄存器中,并在专用于此目的的寄存器中设置系统调用号(例如x86上的EAX)
- 包装函数执行陷阱或等效指令(例如SYSENTER)
- CPU切换到ring0,并调用陷阱处理程序
- 陷阱处理程序检查系统调用号的有效性,并在跳转表中查找到内核函数
- 各自的内核函数检查参数是否有效(例如,范围
buf
到buf + try_read_size
指的是可访问的内存页面,fd
是确实是一个文件描述符).如果有问题,则会生成一个负错误代码(例如-EFAULT),然后将cpu切换回用户模式,然后调用返回到包装器. - 根据文件描述符的类型(在您的情况下为套接字,但可以从块设备或
proc
条目或其他更奇特的条目读取)来调用另一种函数 - 已检查套接字的输入缓冲区:
- 如果缓冲区中有一些数据,则将
min(available,try_read_size)
复制到buf
,该数量将写入返回码寄存器(x86上的EAX)),则cpu切换回用户模式,并且调用返回到包装器. - 如果输入缓冲区为空
- 如果连接已关闭,则将零写入返回码寄存器,将cpu切换回用户模式,然后调用返回到包装器
- 如果连接未关闭
- 如果套接字未阻塞,则将负错误代码(
-EAGAIN
)写入返回代码寄存器,CPU切换回用户模式,并且调用返回到包装器. - 如果套接字是 not non-blocking ,则该过程将被挂起
- A wrapper function provided by glibc is called
- The wrapper function puts the parameters passed on the stack into registers and sets the syscall number in the register dedicated for that purpose (e.g. EAX on x86)
- The wrapper function executes a trap or equivalent instruction (e.g. SYSENTER)
- The CPU switches to ring0, and the trap handler is invoked
- The trap handler checks the syscall number for validity and looks it up in a jump table to kernel functions
- The respective kernel function checks whether arguments are valid (e.g. the range
buf
tobuf+try_read_size
refers to accessible memory pages,fd
is really a file descriptor). If something is amiss, a negative error code (e.g. -EFAULT) is generated, the cpu is switched back to user mode and the call returns to the wrapper. - Another function is called depending on the file descriptor's type (in your case a socket, but one could read from a block device or a
proc
entry or something more exotic) - The socket's input buffer is checked:
- If there is some data in the buffer,
min(available, try_read_size)
is copied tobuf
, the amount is written to the return code register (EAX on x86), the cpu is switched back to user mode and the call returns to the wrapper. - If the input buffer is empty
- If the connection has been closed, zero is written to the return code register, the cpu is switched back to user mode and the call returns to the wrapper
- If the connection has not been closed
- A negative error code (
-EAGAIN
) is written to the return code register if the socket is nonblocking, the cpu is switched back to user mode and the call returns to the wrapper. - The process is suspended if the socket is not non-blocking
- 如果为正数或零,则返回值.
- 如果为负,则将errno设置为负值(报告为正错误)并返回-1
- If positive or zero, it returns the value.
- If negative, it sets errno to the negated value (a positive error is reported) and returns -1
这篇关于Linux套接字调用读取后会发生什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- A negative error code (
- If there is some data in the buffer,
- 如果套接字未阻塞,则将负错误代码(
- 如果缓冲区中有一些数据,则将
查看全文