这篇笔记来看看TCP对accept()系统调用的实现。
1. 内核入口
//从注释中也可以看出accept()系统调用要做的事情:
//1.建立一个新的套接字供服务器端和客户端通信
//2.创建一个新的fd供应用程序后续读写该套接字
/*
* For accept, we attempt to create a new socket, set up the link
* with the client, wake up the client, then return the new
* connected fd. We collect the address of the connector in kernel
* space and move it to user at the very end. This is unclean because
* we open the socket then return an error.
*
* 1003.1g adds the ability to recvmsg() to query connection pending
* status to recvmsg. We need to add that support in a way thats
* clean when we restucture accept also.
*/
asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen)
{
struct socket *sock, *newsock;
struct file *newfile;
int err, len, newfd, fput_needed;
char address[MAX_SOCK_ADDR];
//根据监听套接字的fd找到监听套接字对应的套接字结构struct scoket
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out;
//为新的通信套接字分配套接字结构struct socket
err = -ENFILE;
if (!(newsock = sock_alloc()))
goto out_put;
//新的套接字类型和操作函数集与监听套接字相同
newsock->type = sock->type;
newsock->ops = sock->ops;
/*
* We don't need try_module_get here, as the listening socket (sock)
* has the protocol module (sock->ops->owner) held.
*/
__module_get(newsock->ops->owner);
//为新创建的通信套接字结构分配文件描述符fd
newfd = sock_alloc_fd(&newfile);
if (unlikely(newfd < 0)) {
err = newfd;
sock_release(newsock);
goto out_put;
}
//将fd与socket关联起来
err = sock_attach