
文章目录1 UDP 原理1.1 分离、分用问题1.2 内核数据结构2 守护进程2.1 进程组与作业2.2 会话2.3 手写守护进程1 UDP 原理1.1 分离、分用问题UDP内核数据结构structudphdr{__u16 source;__u16 dest;__u16 len;__u16 check;};UDP 报头由4个部分组成总共8字节。16位 UDP 长度限制了数据长度必须小于等于6553564KB。UDP在发送数据时是数据报这就意味着不会拆包也不会合并。UDP作为网络层协议需要解决两个问题报头有效载荷如何分离 UDP报头长度固定8字节指针指向报头起始地址类型强转后能分离。分用问题交给上层哪个进程一个端口只能一个进程监听一个进程能监听多个端口。理解如何分离有效载荷Windows、Linux操作系统由C为主写的这个报头就是一个结构体。当主机收到数据在网络层指针指向数据做指针类型强转就得到了数据的正确分布。1.2 内核数据结构UDP 没有真正意义上的发送缓冲区因为它不需要错误重传等行为。但有接收缓冲区。sk_buf结构体的四个指针head缓冲区开始。data数据开始。tail数据结束。end缓冲区结束。UDP 将应用层将要发送的数据直接写在的这个缓冲区里面。当向下交付时直接移动指针即可。以上是 UDP 结构体和内核中的缓冲区下面是管理 UDP 的结构体。向上交付时通过指针强转实现该结构体与缓冲区一样都是贯穿三层协议栈。TCP 的管理结构体有所不同之处在于是基于连接的2 守护进程2.1 进程组与作业前台进程一个终端只能有一个特点是能够获得键盘输入。进程组是一组进程的集合且进程组ID(PGID)等于该组的组长(第一个进程)的PID进程组有利于统一管理一组进程。单个进程一组是特殊情况。[jackubuntu]~$psajx|head-1;psajx|grepsleepPPIDPID PGID SID TTY TPGID STATUIDTIME COMMAND1336399133648413364841336399pts/01336484S10010:00sleep10001336399133648513364841336399pts/01336484S10010:00sleep2000前台进程组中每一个前台进程会尝试拥有键盘输入谁先抢到谁先拥有。进程组是站在系统内核角度看的作业是站在 shell 角度看的作业与进程组基本上可以认为是一个东西。创建三个作业(进程组)[jackubuntu]~$jobs[1]Runningsleep1000|sleep2000|sleep3000[2]- Runningsleep1000|sleep2000[3] Runningsleep1000将[1]号后台作业转到前台[jackubuntu]~$fg1sleep1000|sleep2000|sleep3000CtrlZ可以将前台作业暂停。使用bg [作业号]可以继续后台作业也可以使用信号的方式。2.2 会话创建出来的进程组会有一个SID这是会话的session-id。PPIDPID PGID SID TTY TPGID STATUIDTIME COMMAND1336399133689613368961336399pts/01336896S10010:00sleep1000会话是多个进程组的集合。当通过windows的xshell登录linuxlinux会创建一个会话该会话是登录后的第一个进程即终端。退出关闭会话进程组退出。为了让进程组不受会话影响可以使用将进程组守护化。剥离开会话。使进程变成孤儿进程。可以使用系统调用实现intdaemon(intnochdir,intnoclose);2.3 手写守护进程使用setsid函数可以分离会话与进程组。进程组长不能调用setsid因为组长进程 pid 等于 pgid。当调用setsid后成为另一个组长pgid混乱。所以要先 fork让子进程成为守护进程父进程退出。intdaemon(intnoclose,intnodir)// 风云乱世枭雄起唯有一人称英雄。善事善名传五域大仁大意救众生。今朝斩命还世人五域共颂大爱名。才情横溢天资卓持剑登顶必成尊。{pid_tpidfork();if(pid)exit(0);elseif(pid0)return-1;setsid();if(!noclose){close(0);close(1);close(2);}if(!nodir){chdir(/);}return0;}