今天偶尔发现一段描述 http协议在计算机底层实现的描述,读完之后,发上来。
1、服务器网卡接收到数据流后,会立刻给CPU发送中断信号
2、CPU收到后,会立即将手头正在处理的事务全部挂起,并立即检测网卡上是否有DMA芯片
若有就直接发送指令告诉DMA芯片,你将数据流复制到指定的DMA_ZONE的核心内存区中的指定地址段中,然后DMA芯片就开始复制,
3、CPU重新恢复挂起的进程,继续处理
4、当网卡DMA芯片再次发送中断告诉CPU我复制完了,
5、此时CPU将立即挂载正在处理的进程,并激活内核,内核获得CPU控制权后,启动TCP/IP协议栈驱动处理接收到的数据包
6、内核解封装后,发现是一个要访问本机80套接字的SYN请求,于是内核检查socket set发现有这样的监听套接字
7、于是内核将SYN数据复制到Kernel buffer中,进行进一步处理(如判断SYN是否合理),然后准备SYN+ACK数据完成
后经过TCP/IP协议栈驱动封装IP头,链路层帧头,最终这个数据被写入到send buffer中,并立即被复制到网卡传送出去,
8、同时内核还会在连接未完成队列(syn queue)中为这个连接创建一个新项目,并设置为SYN_RECV状态。接着内核进入睡眠,
9、CPU检查被挂起的进程的时间片是否耗尽,没有就将其调度到CPU上继续执行,否则继续将其它用户空间
的进程调度到CPU上执行
10、当Client收到Server的响应后,回应了ACK报文,Server的网卡收到后,又会继续上面的动作
11、CPU会再次挂起正在处理的进程,并将数据接收进来,复制到指定的kernel buffer中(注:DMA_Zone也是Kernel buffer的一部分,
这里不严格区分它们的区别)
11、接着CPU会唤醒内核,又它调度TCP/IP协议栈驱动处理收到的数据包,当解封装后,发现是一个ACK报文,并且数据段大小为0,
这时内核会去检查未完成连接队列,若找到与该ClientInfo(客户端信息)一致的连接信息,则将该连接从未完成连接列表中删除,然后在已完成连接队列中插入该连接信息,并标记状态为ESTABLISHED,
接着将内核中维护的socket set中80监听套接字的状态更为为可读,随后内核让出CPU, 进入睡眠,
12、CPU继续将挂起任务载入CPU上执行,若CPU时间片用完,则将其转入内存进入睡眠,继续下一个用户空间的进程,
13、假设此时调度httpd进程到CPU上执行,它依然是发起select系统调用,此时内核被唤醒,httpd被挂起,内核将根据select的要求,返回内核中socket set的全部状态集,
14、然后,内核进入睡眠,CPU将httpd调入CPU上执行
15、时select开始遍历获取到的socket set集合,当找到自己监听的socket状态为可读时,它将立即解除阻塞,并调用accept()系统调用,此时内核再次被唤醒,
16、内核然后根据accept的要求,将已完成连接队列中与自己建立连接的ClientInfo信息取出来,并删除队列中的信息,然后根据监听套接字生成一个新的专用连接套接字,
把监听套接字的 {源IP,源Port,目标IP,目标Port,协议} 拷贝到这个socket中,接着将该套接字注册到内核管理的socket set中,最后将该专用连接套接字返回,接着内核进入睡眠
17、CPU再次调度httpd进入CPU上执行,httpd获取到专用连接套接字的文件描述符后,将其分配其中一个子进程,由子进程来完成与该用户的后续数据交互,主进程则继续监控监听套接字。
18、若此时httpd的CPU时间片用完了,CPU将会把httpd转入内核睡眠,然后继续其它用户空间的进程;
19、假如此刻Client请求网站主页的数据包到达Server网卡了,网卡依然会采用上面的动作,内核依然会被唤醒,然后内核会调度TCP/IP协议处理数据包,当解封装后,
发现这个数据包是ACK报文,并且数据段大于0,此时内核知道这是一个已经完成的连接请求数据包,于是根据请求报文中的 {源IP,源Port,目标IP,目标Port,协议} 去遍历查找socket set,
若找到对应的专用socket,则将数据拷贝到socket buffer中,并将专用socket的状态设置为可读,然后,内核进入睡眠,CPU继续挂起的任务,
20、当httpd的子进程被调到到CPU上执行时,它通过select系统调用去检查自己监听的专用套接字时,发现自己关心的套接字为可读,于是立即解除阻塞,
21、httpd 调用recvform系统调用,读取数据,此时内核会被唤醒,完成将socket buffer中的数据拷贝到该进程的的内存空间中,然后内核进入睡眠,
22、CPU将httpd子进程调度到CPU上继续执行,httpd子进程读取数据,分析后知道用户要请求网站主页资源,于是再次发起系统调用,获取磁盘中存储的主页数据,
此时内核被唤醒,然后内核调度磁盘驱动,
23、若该磁盘上面有DMA芯片,则内核会直接告诉DMA芯片,你将磁盘中指定柱面,指定扇区,指定磁道上的数据复制到指定的DMA_ZOME中指定的内存区中,然后,内核进入睡眠,CPU继续调度其他进程到CPU上执行。
但是若磁盘上没有DMA芯片,那么内核将自行调度磁盘驱动读取磁盘数据,并等待磁盘驱动完成数据从磁盘拷贝到内核kernel buffer中,再这期间kernel将被阻塞.直到数据拷贝完成,然后,内核进入睡眠,
24、CPU再将httpd子进程调度到CPU上执行,若时间片用完,则再将其调度到内存睡眠,否则就继续让httpd子进程执行,假如此时时间片没有耗尽
25、httpd子进程将会再次发起系统调用,让内核将kernel buffer中的数据拷贝到自己的内存空间中,于是CPU再次将其挂起,内核完成拷贝后,再次进入睡眠,
26、httpd子进程再次被调到CPU上执行,然后httpd子进程根据请求开始返回数据,开始将数据封装上http首部,构建成响应报文后,再次发起系统调用,让内核将数据复制到send buffer中,
27、此时httpd子进程被挂起,内核开始将进程内存空间中的数据拷贝到内核内存空间中的send buffer中,准备调度TCP/IP协议栈驱动对报文做TCP首部,IP首部,链路层帧头等封装,
28、最终这个数据包构建完成,被内核发往网卡的缓冲区中等待发送,当然若网卡上有DMA芯片,内核依然可让DMA芯片来复制数据,完成发生,自己就去睡眠。若没有就只能自己干。
来源:
https://www.cnblogs.com/wn1m/p/10983172.html