Data are received using the recvfrom and recv system calls and the file-related readv and read functions. Because the code of each of these functions is very similar and merges at an early point, only sys_recvfrom, whose code flow diagram is shown in Figure 12-33, is discussed.
A file descriptor to identify the desired socket is passed to the system call. Consequently, the first task is to find the relevant socket. First, fget_light references the descriptor table of the task structure to find the corresponding file instance. sock_from_file determines the associated inode and ultimately the associated socket by using socket_i.
After a few preparations (not discussed here) sock_recvmsg invokes the protocol-specific receive routine sock->ops->recv_msg0. For example, TCP uses tcp_recvmsg to do this. The UDP equivalent is udp_recvmsg. The implementation for UDP is not particularly complicated:
□ If there is at least one packet on the receive queue (implemented by the receive_queue element of the sock structure), it is removed and returned.
□ If the receive queue is empty, it is obvious that no data can be passed to the user process. In this case, the process uses wait_for_packet to put itself to sleep until data arrive.
As the data_ready function of the sock structure is always invoked when new data arrive, the process can be woken at this point.
move_addr_to_user copies the data from kernel space to userspace using the copy_to_user functions described in Chapter 2.
The implementation for TCP follows a similar pattern but is made a little more complicated by the many details and protocol oddities.
Continue reading here: Sending Data
Was this article helpful?