This is a brief introduction about how Linux kernel handles the send system call.
This study is based on kernel version 3.7.2, which is the latest stable kernel when writing this study.
In the latest kernel, the system call is defined using the SYSCALL_DEFINEx macro, in which x is the number of arguments. For example, in order to find the definition of asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, struct sockaddr __user *, int);, you need to grep for SYSCALL_DEFINE6 because it has 6 arguments.
The definition of the system call send can be found at net/socket.c.
Here's the code of the send system call
/*
* Send a datagram down a socket.
*/
SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
unsigned int, flags)
{
return sys_sendto(fd, buff, len, flags, NULL, 0);
}
From the code we know that the send system call is just a simple wrapper function around another system call sendto.
The definition of sendto system call is available in the same file, net/socket.c.
/*
* Send a datagram to a given address. We move the address into kernel
* space and check the user space data area is readable before invoking
* the protocol.
*/
SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
unsigned int, flags, struct sockaddr __user *, addr,
int, addr_len)
Here's the definition of each argument from man 2 sendto:
int fd: the file descriptor of the socket, which is used to send the data tovoid __user * buff: the content which will be send by this system callsize_t len: the length of thebuffunsigned int flags: the bitwise OR of some predefined constantsstruct sockaddr __user * addr: the destination address. Thesendsystem call will set it to NULLint addr_len: the length of theaddrstruct, whichsendsystem call will set it to zero
Here's the description about sendto's behaviour:
-
use
sockfd_lookup_lightto find the corresponding socket descriptor and return itThis function will try to valid if the provided integer
fdis a valid file descriptor, then return the sockeet if it's valid, otherwise returnNULL. -
The message to be send will be assembled, then
sock_sendmsgwill be called to send the message, whose return value will be returned bysendtothen returned tosendcallee.
Below is the description of the sock_sendmsg function call
-
call
init_sync_kiocb, which just inited a newkiocbstruct.kiocbis used as callback if the current system call is asynchronous. -
call
__sock_sendmsg, which is a wrapper aroundsecurity_socket_sendmsgand__sock_sendmsg_nosec.The kernel will try to call
security_socket_sendmsgto check the permission before transmitting, and then call__sock_sendmsg_nosecto send it.Function
__sock_sendmsg_nosecwill callsock->ops->sendmsgto send the messageThe
socket->opsis aproto_ops, which is a protocol-specific struct.
This is a protocol-specific. Depending on the socket type (IPv6/IPv4, UDP/TCP/RAW), there's different implementation of this struct.
For most socket types (at least for IPv4+TCP, IPv4+UDP, IPv4+RAW), the inet_sendmsg function will be called to sendmsg.
In function inet_sendmsg, if the current socket is not binded, kernel will call inet_autobind to bind the socket to a local IP/port.
In inet_sendmsg, it will call socket->sk_prot->sendmsg. We finally reach the transport layer -> internet layer interface.