当前位置:嗨网首页>书籍在线阅读

29-对标准IO的批评

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

3.15 对标准I/O的批评

虽然标准I/O使用广泛,有些专家还是指出了其不足之处。有些函数如fgets(),在某些场景下不满足要求,设计不良。其他函数如gets(),太不安全,差点被逐出标准函数库。

标准I/O最大的诟病是两次拷贝带来的性能开销。当读取数据时,标准I/O会向内核发起read()系统调用,把数据从内核中复制到标准I/O缓冲区。当应用通过标准I/O如fgetc()发起读请求时,又会拷贝数据,这次是从标准I/O缓冲区拷贝到指定缓冲区。写入请求刚好相反:数据先从指定缓冲区拷贝到标准I/O缓冲区,然后又通过write()函数,从标准I/O缓冲区写入内核。

避免两次拷贝的一个解决办法是,每个读请求返回一个指向标准I/O缓冲区的指针。这样,数据就可以直接从标准I/O缓冲区中读取,不需要多余的拷贝操作。如果应用确实需要把数据拷贝到自己本地缓冲区时(可能向其中写数据),总是可以手动地执行拷贝操作。这种实现方式需要提供资源“释放(free)”接口,允许应用在不用缓冲区时发出信号。

写请求会更复杂些,但是还是可以避免两次拷贝。当发起写请求时,记录指针位置,最终当准备将数据刷新到内核时,再通过记录的指针列表把数据写出去。这些可以通过分散-聚集I/O(scatter-gather I/O)模型的writev()函数来实现,这样写请求就只需要单个系统调用。(我们将在下一章探讨分散-聚集I/O)。

现在有一些高度优化的用户缓冲库,它们通过类似刚刚讨论的实现方式来解决两次拷贝问题。还有一些开发者选择实现自己的用户缓冲方案。但是尽管存在这些不同的解决方式,标准I/O仍然很流行。