accept系统调用完成的工作是,从已经完成三次握手的连接队列中取一个连接,进行后续服务;

调用过程中,会重新分配一个socket,以及关联文件和传输控制块,如果应用层需要获取对端信息,则将对端信息拷贝到用户空间;

  1. /*
  2. * For accept, we attempt to create a new socket, set up the link
  3. * with the client, wake up the client, then return the new
  4. * connected fd. We collect the address of the connector in kernel
  5. * space and move it to user at the very end. This is unclean because
  6. * we open the socket then return an error.
  7. *
  8. * 1003.1g adds the ability to recvmsg() to query connection pending
  9. * status to recvmsg. We need to add that support in a way thats
  10. * clean when we restucture accept also.
  11. */
  12.  
  13. SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
  14. int __user *, upeer_addrlen, int, flags)
  15. {
  16. struct socket *sock, *newsock;
  17. struct file *newfile;
  18. int err, len, newfd, fput_needed;
  19. struct sockaddr_storage address;
  20.  
  21. /* 只支持cloexec和nonblock */
  22. if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
  23. return -EINVAL;
  24.  
  25. /* 如果阻塞标记不等&& 有阻塞标记,则替换为O_NONBLOCK */
  26. if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  27. flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
  28.  
  29. /* 找到socket */
  30. sock = sockfd_lookup_light(fd, &err, &fput_needed);
  31. if (!sock)
  32. goto out;
  33.  
  34. err = -ENFILE;
  35.  
  36. /* 分配一个新socket */
  37. newsock = sock_alloc();
  38. if (!newsock)
  39. goto out_put;
  40.  
  41. /* 类型和操作与本端socket相同 */
  42. newsock->type = sock->type;
  43. newsock->ops = sock->ops;
  44.  
  45. /*
  46. * We don't need try_module_get here, as the listening socket (sock)
  47. * has the protocol module (sock->ops->owner) held.
  48. */
  49. /* 增加模块引用 */
  50. __module_get(newsock->ops->owner);
  51.  
  52. /* 获取新的文件描述符 */
  53. newfd = get_unused_fd_flags(flags);
  54. if (unlikely(newfd < )) {
  55. err = newfd;
  56. sock_release(newsock);
  57. goto out_put;
  58. }
  59.  
  60. /* 分配新的文件 */
  61. newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
  62. if (IS_ERR(newfile)) {
  63. err = PTR_ERR(newfile);
  64. put_unused_fd(newfd);
  65. sock_release(newsock);
  66. goto out_put;
  67. }
  68.  
  69. /* accept检查 */
  70. err = security_socket_accept(sock, newsock);
  71. if (err)
  72. goto out_fd;
  73.  
  74. /* 执行具体的accept操作 */
  75. err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
  76. if (err < )
  77. goto out_fd;
  78.  
  79. /* 指定了获取对端信息 */
  80. if (upeer_sockaddr) {
  81. if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
  82. &len, ) < ) {
  83. err = -ECONNABORTED;
  84. goto out_fd;
  85. }
  86.  
  87. /* 拷贝对端地址到用户空间结构 */
  88. err = move_addr_to_user(&address,
  89. len, upeer_sockaddr, upeer_addrlen);
  90. if (err < )
  91. goto out_fd;
  92. }
  93.  
  94. /* File flags are not inherited via accept() unlike another OSes. */
  95.  
  96. /* 绑定描述符和文件 */
  97. fd_install(newfd, newfile);
  98. err = newfd;
  99.  
  100. out_put:
  101. fput_light(sock->file, fput_needed);
  102. out:
  103. return err;
  104. out_fd:
  105. fput(newfile);
  106. put_unused_fd(newfd);
  107. goto out_put;
  108. }
  109.  
  110. SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
  111. int __user *, upeer_addrlen)
  112. {
  113. return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, );
  114. }

inet_accept函数调用传输层的accept操作,并且返回新的连接控制块,新的连接控制块需要与新的socket进行关联,accept完成,将新socket的状态设置为已连接状态;

  1. /*
  2. * Accept a pending connection. The TCP layer now gives BSD semantics.
  3. */
  4.  
  5. int inet_accept(struct socket *sock, struct socket *newsock, int flags,
  6. bool kern)
  7. {
  8. struct sock *sk1 = sock->sk;
  9. int err = -EINVAL;
  10.  
  11. /* 执行传输层的accept操作 */
  12. struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err, kern);
  13.  
  14. if (!sk2)
  15. goto do_err;
  16.  
  17. lock_sock(sk2);
  18.  
  19. /* rps处理 */
  20. sock_rps_record_flow(sk2);
  21. WARN_ON(!(( << sk2->sk_state) &
  22. (TCPF_ESTABLISHED | TCPF_SYN_RECV |
  23. TCPF_CLOSE_WAIT | TCPF_CLOSE)));
  24.  
  25. /* 控制块连接到新的socket */
  26. sock_graft(sk2, newsock);
  27.  
  28. /* 设置新socket的状态为连接 */
  29. newsock->state = SS_CONNECTED;
  30. err = ;
  31. release_sock(sk2);
  32. do_err:
  33. return err;
  34. }
  35. EXPORT_SYMBOL(inet_accept);

TCP层对于accept的实现,请移步另外一篇文章:<TCP层accept系统调用的实现分析>;

accept系统调用的更多相关文章

  1. accept系统调用内核实现

    用户态对accept的标准使用方法: if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_siz ...

  2. TCP层accept系统调用的实现分析

    inet_csk_accept函数实现了tcp协议accept操作,其主要完成的功能是,从已经完成三次握手的队列中取控制块,如果没有已经完成的连接,则需要根据阻塞标记来来区分对待,若非阻塞则直接返回, ...

  3. Linux进程间通信(八):流套接字 socket()、bind()、listen()、accept()、connect()、read()、write()、close()

    前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进程.通常我们使用socket进行网络编 ...

  4. linux独有的sendfile系统调用--“零拷贝,高效”

    参考:http://blog.csdn.net/caianye/article/details/7576198 如今几乎每个人都听说过Linux中所谓的"零拷贝"特性,然而我经常碰 ...

  5. socket编程之accept()函数【转载】

    名称 accept() 接收一个套接字中已建立的连接 使用格式 #include <sys/types.h> #include <sys/socket.h> int accep ...

  6. Netty源码细节-accept、read(Linux os层 + Netty层代码细节)(转)

    原文:http://budairenqin.iteye.com/blog/2215899 这篇分析一下accept的细节, 我觉得网络IO相关开发很多时候不能仅仅局限于java层, 尤其从accept ...

  7. 从Linux源码看Socket(TCP)的accept

    从Linux源码看Socket(TCP)的accept 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就从Linux源码的角度看下Serve ...

  8. socket 函数

    1.创建套接字并返回一个描述符,该描述符可以用来访问套接字 #include<sys/types.h> #include<sys/socket.h>  int socket(i ...

  9. 【linux草鞋应用编程系列】_5_ Linux网络编程

    一.网络通信简介   第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章.   二.linux网络通信     在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...

随机推荐

  1. path变量修改后无法保存

    Eclipse启动时出现错误: A Java Runtime Environment (JRE) or Java Development Kit(JDK) must be available in o ...

  2. MySql--学习成长过程

    MySql--学习成长过程 模拟测试: QQ数据库管理 一.创建数据库并添加关系和测试数据 1 ##创建QQ数据库,完成简单的测试 2 3 #创建数据库 4 DROP DATABASE IF EXIS ...

  3. static变量 方法 类 和final

    static变量:声明为static的变量实质上就是全局变量.当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量.静态变量与静态方法类似.所有此类实例共 ...

  4. BZOJ 4454: C Language Practice

    4454: C Language Practice Time Limit: 20 Sec  Memory Limit: 24 MBSubmit: 501  Solved: 112[Submit][St ...

  5. NetApp常用巡检命令

    常用检查命令 environment status 查看环境信息 version 查看OS版本 sysconfig -v 查看系统信息(设备序列号 系统软.硬件信息等) sysconfig -a 查看 ...

  6. 【codeforces 528D】 Fuzzy Search

    http://codeforces.com/problemset/problem/528/D (题目链接) 题意 给定母串和模式串,字符集大小为${4}$,给定${k}$,模式串在某个位置匹配当且仅当 ...

  7. 《Linux内核设计与实现》学习总结 Chap3

    第三章 进程管理 进程是Unix操作系统抽象概念中最基本的一种.我们拥有操作系统就是为了运行用户程序,因此,进程管理就是所有操作系统的心脏所在. 3.1进程 概念: 进程:处于执行期的程序.但不仅局限 ...

  8. sqoop 补充

    1.用 sqoop 将MySQL中的数据导入hbase中 sqoop import \--connect jdbc:mysql://***.***.*.***:3306/mysql \--hbase- ...

  9. getopt_long

    http://blog.csdn.net/lanyan822/article/details/7692013 在程序中难免需要使用命令行选项,可以选择自己解析命令行选项,但是有现成的,何必再造轮子.下 ...

  10. 【Asp.net入门15】第一个Asp.net应用程序-输入验证

    前言 所谓输入验证,顾名思义就是验证用户输入符不符合要求.前面我们已经完成了这个简单的应用程序,但还有一个问题需要解决:用户可以在Default.aspx窗体中 提交任何数据,甚至可以提交根本不包含任 ...