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.
How system call is defined
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
forSYSCALL_DEFINE6
because it has 6 arguments.
The definition of the system call send
can be found at net/socket.c
.
How is the send
system call handled
Definition of send
system call
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
.
Definition of sendto
system call
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 thebuff
unsigned int flags
: the bitwise OR of some predefined constantsstruct sockaddr __user * addr
: the destination address. Thesend
system call will set it to NULLint addr_len
: the length of theaddr
struct, whichsend
system call will set it to zero
Here's the description about sendto
's behaviour:
-
use
sockfd_lookup_light
to find the corresponding socket descriptor and return itThis function will try to valid if the provided integer
fd
is a valid file descriptor, then return the sockeet if it's valid, otherwise returnNULL
. -
The message to be send will be assembled, then
sock_sendmsg
will be called to send the message, whose return value will be returned bysendto
then returned tosend
callee.
Definition of sock_sendmsg
call
Below is the description of the sock_sendmsg
function call
- call
init_sync_kiocb
, which just inited a newkiocb
struct.kiocb
is used as callback if the current system call is asynchronous. -
call
__sock_sendmsg
, which is a wrapper aroundsecurity_socket_sendmsg
and__sock_sendmsg_nosec
.The kernel will try to call
security_socket_sendmsg
to check the permission before transmitting, and then call__sock_sendmsg_nosec
to send it.Function
__sock_sendmsg_nosec
will callsock->ops->sendmsg
to send the messageThe
socket->ops
is aproto_ops
, which is a protocol-specific struct.
Definition of proto_ops
struct and its sendmsg
function
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 bind
ed, 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.