1. 程式人生 > >accept系統調用

accept系統調用

!= put msg proto syn when temp als light

  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 < 0)) { 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 < 0) 77 goto out_fd; 78 79 /* 指定了獲取對端信息 */ 80 if (upeer_sockaddr) { 81 if (newsock->ops->getname(newsock, (struct sockaddr *)&address, 82 &len, 2) < 0) { 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 < 0) 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, 0); 114 }

 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(!((1 << 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 = 0;
31     release_sock(sk2);
32 do_err:
33     return err;
34 }
35 EXPORT_SYMBOL(inet_accept);

紅色部分的傳輸層accept實現在tcp代碼閱讀時再做分析;

accept系統調用