跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
IO模型
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:IO模型}} '''IO模型'''(Input/Output Model)是操作系统中描述应用程序与外部设备(如磁盘、网络等)进行数据交互的核心机制。不同的IO模型对系统性能、资源占用和编程复杂度有显著影响,是面试高频考点和系统调优的关键知识点。 == 基本概念 == IO操作分为两个阶段: # '''准备阶段''':内核等待数据就绪(如网络数据到达内核缓冲区) # '''拷贝阶段''':将数据从内核缓冲区拷贝到用户空间 根据这两个阶段的处理方式不同,主要分为五种IO模型: * 阻塞IO(Blocking IO) * 非阻塞IO(Non-blocking IO) * IO多路复用(IO Multiplexing) * 信号驱动IO(Signal-driven IO) * 异步IO(Asynchronous IO) <mermaid> flowchart TD A[发起IO请求] --> B{数据是否就绪?} B -->|是| C[数据拷贝] B -->|否| D[等待/轮询/回调] C --> E[完成通知] </mermaid> == 阻塞IO(Blocking IO)== 最基础的IO模型,进程在数据就绪前会被挂起。 === 特点 === * 同步阻塞模式 * 系统调用(如read())直到数据到达才返回 * 简单但效率低 === 代码示例 === <syntaxhighlight lang="c"> #include <unistd.h> int main() { char buf[1024]; // 阻塞等待输入(示例:标准输入) ssize_t n = read(STDIN_FILENO, buf, sizeof(buf)); write(STDOUT_FILENO, buf, n); return 0; } </syntaxhighlight> == 非阻塞IO(Non-blocking IO)== 通过设置文件描述符为非阻塞模式,立即返回错误码而不是阻塞等待。 === 特点 === * 同步非阻塞模式 * 需要轮询检查状态 * 消耗CPU资源 === 代码示例 === <syntaxhighlight lang="c"> #include <fcntl.h> #include <unistd.h> int main() { int flags = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); char buf[1024]; while(1) { ssize_t n = read(STDIN_FILENO, buf, sizeof(buf)); if(n > 0) { write(STDOUT_FILENO, buf, n); break; } else if(errno == EAGAIN) { usleep(100000); // 100ms延迟 } } return 0; } </syntaxhighlight> == IO多路复用(IO Multiplexing)== 使用select/poll/epoll等系统调用同时监控多个文件描述符。 === 对比 === {| class="wikitable" ! 方法 !! 描述 !! 最大fd数 !! 效率 |- | select || 位图遍历检查 || FD_SETSIZE || O(n) |- | poll || 链表结构存储 || 无限制 || O(n) |- | epoll || 事件回调机制 || 无限制 || O(1) |} === epoll示例 === <syntaxhighlight lang="c"> #include <sys/epoll.h> #define MAX_EVENTS 10 int main() { int epfd = epoll_create1(0); struct epoll_event ev, events[MAX_EVENTS]; ev.events = EPOLLIN; ev.data.fd = STDIN_FILENO; epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev); while(1) { int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); for(int i = 0; i < nfds; i++) { if(events[i].data.fd == STDIN_FILENO) { char buf[1024]; read(STDIN_FILENO, buf, sizeof(buf)); // 处理数据... } } } return 0; } </syntaxhighlight> == 信号驱动IO(Signal-driven IO)== 通过SIGIO信号通知进程数据就绪,无需主动轮询。 === 实现步骤 === 1. 设置信号处理程序 2. 指定文件描述符的属主进程 3. 启用信号驱动IO == 异步IO(Asynchronous IO)== 最先进的IO模型,全程无阻塞。 === 特点 === * 异步非阻塞模式 * 内核完成所有操作后通知应用 * POSIX标准(aio_*函数) === 对比同步IO === <math> \begin{cases} 同步IO:\text{应用主动参与数据拷贝阶段} \\ 异步IO:\text{内核完成所有操作后通知} \end{cases} </math> == 实际应用场景 == * '''Web服务器''':Nginx使用epoll实现高并发 * '''数据库系统''':Redis采用IO多路复用 * '''高性能计算''':MPI库使用异步IO重叠计算与通信 == 性能比较 == <mermaid> barChart title IO模型延迟比较 x-axis 模型 y-axis 延迟(ms) bar 阻塞IO: 200 bar 非阻塞IO: 180 bar IO多路复用: 50 bar 异步IO: 30 </mermaid> == 常见面试问题 == 1. 五种IO模型的核心区别是什么? 2. 为什么epoll比select/poll效率高? 3. 异步IO与信号驱动IO的关键差异? 4. 如何理解"非阻塞IO本质上仍是同步的"? == 进阶阅读建议 == * 《UNIX网络编程》- Stevens * Linux man pages: select(2), epoll(7), aio(7) * 边缘触发(ET) vs 水平触发(LT)模式 [[Category:操作系统]] [[Category:面试八股文结构]] [[Category:计算机科学]] [[Category:面试技巧]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)