从内核接收数据到EPOLL原理

本文深入探讨了Linux内核如何接收数据,包括从网卡接收数据到内核缓冲区,再到socket接收缓冲区的过程。接着,详细介绍了中断处理流程,解释了阻塞不占用CPU资源的原因,并阐述了工作队列和等待队列的概念。文章还对比分析了BIO、select、poll和epoll四种IO多路复用机制的工作原理,强调epoll在性能和效率上的优势,如避免遍历整个文件描述符集合和减少用户态与内核态之间的数据拷贝。
摘要由CSDN通过智能技术生成

一、内核接收数据流程

内核接收数据.png

1.网卡发现 MAC 地址符合,就将包收进来;发现 IP 地址符合,根据 IP 头中协议项,知道上一层是 TCP 协议;

2.DMA把TCP数据包copy到内核缓冲区;

3.触发CPU中断,中断程序摘除TCP头通过socket五要素(源IP/PORT、目的IP/PORT、协议)找到对应的socket文件,并把原始二进制数据报copy到socket接收缓冲区;

4.中断程序唤醒被阻塞的内核线程;

5.内核线程切换到用户线程把数据从socket接口缓冲区copy到应用内存;

二、中断处理流程

中断处理.png

I/O发出的信号的异常代码,拿到异常代码之后,CPU就会触发异常处理的流程。计算机在内存里会保存中断向量表,用来存放不同的异常代码对应的异常处理程序所在的地址。

CPU在拿到了异常码之后,会先把当前的程序执行的现场,保存到程序栈里面,然后根据异常码查询,找到对应的异常处理程序,最后把后续指令执行的指挥权,交给这个异常处理程序。

异常处理程序结束之后返回到原来指令执行的位置继续执行;

三、阻塞不占用 cpu

网卡何时接收到数据是依赖发送方和传输路径的,这个延迟通常都很高,是毫秒(ms)级别的。而应用程序处理数据是纳秒(ns)级别的。也就是说整个过程中,内核态等待数据,处理协议栈是个相对很慢的过程。这么长的时间里,用户态的进程是无事可做的,因此用到了“阻塞(挂起)”。

阻塞是进程调度的关键一环,指的是进程在等待某事件发生之前的等待状态。请看下表,在 Linux 中,进程状态大致有 7 种(在 include/linux/sched.h 中有更多状态):

从说明中可以发现,“可运行状态”会占用 CPU 资源,另外创建和销毁进程也需要占用 CPU 资源(内核)。重点是,当进程被"阻塞/挂起"时,是不会占用 CPU 资源的。

为了支持多任务,Linux 实现了进程调度的功能(CPU 时间片的调度)。而这个时间片的切换,只会在“可运行状态”的进程间进行。因此“阻塞/挂起”的进程是不占用 CPU 资源的。

四、工作队列和等待队列

工作队列和等待队列.png

工作队列:为了方便时间片的调度,所有“可运行状态”状态的进程组成的队列;

fd文件列表:内核打开的文件句柄,Linux一切皆文件,用户线程执行创建Socket时内核就会创建一个由文件系统管理的sock对象;

sock:socket内核中的数据结构,主要包含发送缓冲区、接收缓冲区、等待队列;

structsock{__u32  daddr;/* 外部IP地址  */__u32  rcv_saddr;/* 绑定的本地IP地址  */__u16  dport;/* 目标端口  */__u16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农老K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值