技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> 在Linux进行IO的正确姿势

在Linux进行IO的正确姿势

浏览:3799次  出处信息

   很多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. 关于IO的同步,异步,阻塞,非阻塞    (阅读:14552)
  2. Linux服务器性能评估    (阅读:8301)
  3. 提升磁盘IO性能的几个技巧    (阅读:7617)
  4. I/O模型-读书笔记    (阅读:6969)
  5. Innodb IO优化-配置优化    (阅读:6755)
  6. 查看 CPU, Memory, I/O and NetFlow    (阅读:6530)
  7. blktrace 深度了解linux系统的IO运作    (阅读:6025)
  8. Linux操作系统内核3.3版本I/O Stack的流图    (阅读:5794)
  9. Linux IO协议栈框图    (阅读:5405)
  10. MySQL Tuning之浅析I/O优化    (阅读:5196)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1