注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析、”(下)“表示分析是从上向下分析。
在博文Linux内核--网络栈实现分析(二)--数据包的传递过程(上)中分析了数据包从网卡设备经过驱动链路层,网络层,传输层到应用层的过程。
本文就分析一下本机产生数据是如何通过传输层,网络层到达物理层的。
综述来说,数据流程图如下:
一、应用层
应用层可以通过系统调用或文件操作来调用内核函数,BSD层的sock_write()函数会调用INET层的inet_wirte()函数。
/* * Write data to a socket. We verify that the user area ubuf..ubuf+size-1 is * readable by the user process. */ static int sock_write(struct inode *inode, struct file *file, char *ubuf, int size) { struct socket *sock; int err; if (!(sock = socki_lookup(inode))) { printk("NET: sock_write: can't find socket for inode!\n"); return(-EBADF); } if (sock->flags & SO_ACCEPTCON) return(-EINVAL); if(size<0) return -EINVAL; if(size==0) return 0; if ((err=verify_area(VERIFY_READ,ubuf,size))<0) return err; return(sock->ops->write(sock, ubuf, size,(file->f_flags & O_NONBLOCK))); } |
INET层会调用具体传输层协议的write函数,该函数是通过调用本层的inet_send()函数实现功能的,inet_send()函数的UDP协议对应的函数为udp_write()
static int inet_send(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags) { struct sock *sk = (struct sock *) sock->data; if (sk->shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 1); return(-EPIPE); } if(sk->err) return inet_error(sk); /* We may need to bind the socket. */ if(inet_autobind(sk)!=0) return(-EAGAIN); return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, flags)); } static int inet_write(struct socket *sock, char *ubuf, int size, int noblock) { return inet_send(sock,ubuf,size,noblock,0); } |