1、当执行socket()系统调用时,内核就访问进程表结构。这个结构的p_fd指向进程的filedesc结构,filedesc结构中的fd_ofiles是指向文件表结构file的指针数组的指针。file中的f_data指向socket结构,file中的f_type填写DTYPE_SOCKET,socket结构中的so_type填写SOCK_DGRAM,socket结构中的so_pcb指向Internet协议控制块PCB链表中的一个成员。参照图1-5。
当进程调用send_to系统调用时,内核从描述符值开始,使用fd_ofiles索引到file结构指针向量,直到描述符所对应的file结构,结构file指向socket结构,结构socket带有指向结构inpcb的指针。
当一个UDP数据报到达一个网络接口时,内核搜索所有UDP协议控制块,寻找一个合适的,至少要根据目的UDP端口号,可能还要根据目的IP地址、源IP地址和源端口号。一旦定位所找到的inpcb,内核就能通过inp_socket指针来找到相应的socket结构。
当进程调用socket系统调用的时候,以下内核数据结构是一起被分配和链接起来的:一个DTYPE_SOCKET类型的file结构、一个socket结构和一个inpcb结构。
2、当进程调用sendto系统调用(1)插口层把目标插口地址结构和用户数据复制到mbuf链中(2)UDP输出例程在用户数据前面添加并初始化IP层和UDP层(3)IP输出例程填写IP首部剩余的字段,包括IP检验和,确定数据报应发到哪个输出接口(IP路由功能),必要时,对IP报文分片(4)以太网输出例程先通过ARP协议将32位IP地址转换成相应的48位以太网地址,然后将以太网首部添加到IP头前面,之后此mbuf链表被添加到此接口的输出队列队尾,函数调用返回。(5)接口按顺序处理队列中的mbuf,它把mbuf中的数据复制到它的传输缓存中,并且开始输出。
进程调用sendto时一共对数据进行了三次遍历(1)将数据由用户的缓存复制到mbuf中(2)计算UDP检验和(3)将mbuf中的数据复制到发送接口的传输缓存中。
3、输入处理与输出处理不同,因为输入是异步的,它是通过一个接收完成硬中断来驱动以太网设备驱动程序来接收一个输入分组,它将数据从设备读到mbuf链表中,通过以太网帧中的类型字段来确定由IP协议层来接收此分组,从而将mbuf加入到IP输入队列中,然后产生一个软中断来执行IP输入例程,这样这个设备中断处理就完成了。
IP输入是异步的,并且通过一个软中断来执行,当接口层在系统的一个接口上收到一个IP数据报时,就设置这个软中断,当IP输入例程执行它时,循环处理在它的输入队列中的每一个IP数据报,验证IP首部检验和,处理IP选项,验证数据报被传递到正确的主机,如果系统被配置成一个路由器时,转发目的地址是其它IP的数据报,通过IP首部中标识的协议调用UDP输入例程去处理UDP数据报。
UDP输入例程验证UDP首部中的各字段,然后在PCB链表中寻找一个与接收的UDP数据报的IP和端口号匹配的协议控制块,通过它的成员inp_socket找到相应的插口结构,并允许接收的数据在此插口排队。
调用recvfrom阻塞的进程被唤醒,UDP层追加到插口接收队列中的数据被内核从mbuf复制到应用程序的缓存中。
4、sendto函数调用直到数据被添加到输出接口的队列队尾才返回。recvfrom调用先阻塞,数据到达输入接口触发硬中断,硬中断触发驱动程序将数据从设备读到IP输入队列中,然后触发软中断,软中断触发IP例程将数据复制到插口的接收队列中,唤醒阻塞的进程,recvfrom将数据由内核复制到应用程序的缓存中。参考图1-12。
网友评论