IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

在Linux进行IO的正确姿势

idea's blog 2015-05-11 23:25:24 累计浏览 4,588 次
本机暂存

   很多C/C++程序虽然在做网络编程, 但大多用别人封装好的库, 对底层不甚了解, 感觉 IO 操作不是很简单吗? 我敢说, 大多数人进行 IO 的姿势都不对, 所谓的 IO, 主要是 read()/write() 两个函数.

   先说错误的 IO 读操作:

int ret = read(fd, buf, len);
if(ret == -1){
    exit(-1);
}else if(ret == 0){
    close(fd);
}

   看起来好像很正确的样子, 返回值也判断了, 不仅判断 -1, 还判断 0, 应该姿势正确吧? 错! 完全错误! 因为你忽略了 errno 的处理. 仔细看文档, 函数返回 -1 不能完全代表 fd 错误, 还需要结合 errno.

   接下来这样改:

int ret = read(fd, buf, len);
if(ret == -1){
    if(errno == EINTR){
        // 怎么办?
    }else if(errno == EAGAIN){
        // 怎么办?
    }
    exit(-1);
}else if(ret == 0){
    close(fd);
}

   EINTR 表示 read() 函数调用被系统中断了, 调用者和 fd 都没有问题, 有问题的是操作系统. 而 EAGAIN 是在非阻塞 IO 时会出现. 上面的代码判断了 errno, 但不知道下一步该怎么做, 还不行.

   在 Linux 下进行 IO 操作的正确姿势是:

while(1){
    int ret = read(fd, buf, len);
    if(ret == -1){
        if(errno == EINTR){
            continue;
        }else if(errno == EAGAIN){
            // 根据你和调用者的约定, 返回一个数值告诉它再次重试
            // 一般是结合 select/epoll 等 IO 多路复用函数
        }
        exit(-1);
    }else if(ret == 0){
        close(fd);
    }
}

   没错, 在 read() 外面包一个 while(0). 以后你看到有谁写的 read() 代码不是被包含在一个死循环里, 你就可以下结论说这段代码不完善.

   写 IO 的 write() 函数也是类似用法. 建议有心人可以参考 sim 框架的代码, 看看别人是怎么做的, 程序员应该多造轮子, 但不要关起门来造车.

同分类推荐文章

  1. Vibe新开源项目 - Vaala AI Gateway (2026-05-17 02:10:19)
  2. SmartPerfetto 架构文章 Q&A:8 个深度技术问答 (2026-04-10 11:00:00)
  3. 让 AI 把我的 PHP 博客重写成 Go (2026-03-27 18:33:54)

查看更多 后端 文章 →

建议继续学习

  1. 关于IO的同步,异步,阻塞,非阻塞 (累计阅读 16,587)
  2. Linux如何统计进程的CPU利用率 (累计阅读 16,203)
  3. libcurl的使用总结(二) (累计阅读 15,002)
  4. 我的 RHCA 之路 (累计阅读 13,926)
  5. Linux内存点滴 用户进程内存空间 (累计阅读 13,049)
  6. 给程序员新手的一些建议 (累计阅读 13,024)
  7. Linux 性能监控、测试、优化工具 (累计阅读 12,950)
  8. 关于linux内存free的一些事情 (累计阅读 12,750)
  9. ps - 按进程消耗内存多少排序 (累计阅读 12,604)
  10. Google怎么用linux (累计阅读 12,466)