Skip to content

零拷贝是什么 ​

sendfile 可以避免这个用户态和内核态的频繁切换

redis ,nginx,netty 是依赖什么做的这么高性能? ​

主要是依赖Reactor 模式 ,这里指的就是反应堆模式,就是对事件反应,也就是来了一个事件,Reactor 就有对应的反应/响应,Reacto模式主要由Reactor 和处理资源池这两个核心部分组成, Reactor 负责监听和分发事件,事件类型包括连接事件,读写事件; 处理资源池负责处理事件,如 read-> 业务逻辑-> send

用户态和内核态有什么区别? ​

用户态和内核态是 CPU 的两种运行级别,区别在于权限:内核态可以执行所有指令、访问所有硬件和内存;用户态只能执行普通指令,不能直接操作硬件。在 x86 架构上,它们分别对应特权级 Ring 0 和 Ring 3。

两种状态的区别 ​

对比项用户态内核态
运行的代码普通应用程序操作系统内核
指令权限只能执行非特权指令可执行全部指令,包括特权指令
访问资源不能直接访问硬件和内核内存可访问所有硬件和内存
出错影响通常只影响当前进程可能导致整个系统崩溃

内核态负责的核心工作包括:进程调度、内存管理、文件系统、设备驱动、网络协议栈等。

为什么要划分两种状态 ​

  • 安全:应用程序不能随意读写硬件或其他进程的内存,恶意或有缺陷的程序无法直接破坏系统。
  • 稳定:用户程序崩溃只影响自身,不会拖垮整个操作系统。
  • 隔离与可维护:内核与应用之间有清晰的边界,应用只能通过规定的接口使用系统服务,便于模块化设计。

如何从用户态进入内核态 ​

主要有三种途径:

  1. 系统调用:程序主动请求内核服务,如 read、write、open、fork。这是最常见的方式。
  2. 异常:程序执行出错,如缺页、除零,CPU 自动切到内核处理。
  3. 外部中断:硬件设备发出信号,如磁盘读写完成、网卡收到数据、时钟中断。

以读文件为例:

c
char buf[1024];
int fd = open("data.txt", O_RDONLY);  // 系统调用,陷入内核
read(fd, buf, sizeof(buf));            // 内核从磁盘读数据,拷贝到用户缓冲区

切换的开销 ​

每次切换都要保存和恢复寄存器、切换栈,还可能影响 CPU 缓存和 TLB,因此频繁切换会降低性能。很多高性能技术正是为了减少切换和数据拷贝:

  • 零拷贝(sendfile、mmap):减少用户态与内核态之间的数据复制。
  • IO 多路复用(epoll):一次系统调用监听大量连接。
  • 用户态协程:在用户态完成调度,避免线程切换陷入内核。

总结 ​

用户态与内核态的划分是操作系统安全和稳定的基础。应用程序通过系统调用、异常、中断进入内核态,切换有一定开销,这也是零拷贝、epoll 等优化手段存在的原因。


📮 联系方式

微信:BuZhiCoder | QQ:1776418445 扫码添加,备注「求职」优先通过

微信二维码

基于 VitePress 搭建

🌟训练营🤖AI面试📄做简历💻刷题