公开学习文档

公开学习文档


应用层

<h2>概述</h2> <p>1、send 系统调用,先根据 fd 找到对应的 socket,然后调用 <code>sock-&amp;gt;ops-&amp;gt;sendmsg()</code>,对于 TCP 而言,则是 <code>inet_sendmsg</code></p> <h2>分析</h2> <p>应用层调用 send,对应的代码:</p> <pre><code class="language-c">// file: net/socket.c /* * 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); } /* * 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) { struct socket *sock; struct sockaddr_storage address; int err; struct msghdr msg; struct iovec iov; int fput_needed; if (len &amp;gt; INT_MAX) len = INT_MAX; sock = sockfd_lookup_light(fd, &amp;amp;err, &amp;amp;fput_needed); // 根据 fd 找到 socket if (!sock) goto out; iov.iov_base = buff; iov.iov_len = len; msg.msg_name = NULL; msg.msg_iov = &amp;amp;iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_namelen = 0; if (addr) { err = move_addr_to_kernel(addr, addr_len, &amp;amp;address); if (err &amp;lt; 0) goto out_put; msg.msg_name = (struct sockaddr *)&amp;amp;address; msg.msg_namelen = addr_len; } if (sock-&amp;gt;file-&amp;gt;f_flags &amp;amp; O_NONBLOCK) flags |= MSG_DONTWAIT; msg.msg_flags = flags; err = sock_sendmsg(sock, &amp;amp;msg, len); // 进一步调用 out_put: fput_light(sock-&amp;gt;file, fput_needed); out: return err; } int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct kiocb iocb; struct sock_iocb siocb; int ret; init_sync_kiocb(&amp;amp;iocb, NULL); iocb.private = &amp;amp;siocb; ret = __sock_sendmsg(&amp;amp;iocb, sock, msg, size); if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&amp;amp;iocb); return ret; } EXPORT_SYMBOL(sock_sendmsg); static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size) { int err = security_socket_sendmsg(sock, msg, size); return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); } static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size) { struct sock_iocb *si = kiocb_to_siocb(iocb); si-&amp;gt;sock = sock; si-&amp;gt;scm = NULL; si-&amp;gt;msg = msg; si-&amp;gt;size = size; return sock-&amp;gt;ops-&amp;gt;sendmsg(iocb, sock, msg, size); // 对于 TCP 而言,socket-&amp;gt;ops = inet_stream_ops。sendmsg = inet_sendmsg } </code></pre>

页面列表

ITEM_HTML