3.7 函数read
调用read函数从打开文件中读数据。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes); // 返回值:读到的字节数,若已到文件尾,返回0;若出错,返回-1
如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0.
有多种情况可使实际读到的字节数少于要求读的字节数:
- 读普通文件时,在读要求字节数之前已到达了文件尾端。
- 当从终端设备读时,通常一次最多读一行。
- 当从网络读时,网络中的缓冲机制可能造成但绘制小于所要求读的字节数。
- 当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。
- 当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录。
- 当一信号造成中断,而已经读了部分数据量时。
读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。
POSIX.1从几个方面对read函数的原型做了更改。经典的原型定义是:
int read(int fd, char *buf, unsigned nbytes);
- 首先,为了与ISO C一致,第二个参数由char *改为void *。在ISO C中,类型void *用于便是通用指针。
- 其次,返回值必须是一个带符号整型(ssize_t),以保证能够返回正整数字节数、0或-1。
- 最后,第三个参数在历史上是一个无符号整型,这允许一个16位的实现一次读或写的数据可以多达65534个字节。
3.8 函数write
调用write函数向打开文件中写数据。
#include <unistd.h>
ssize_t write(int fd, void * buf, size_t nbytes); // 返回值:若成功,返回已写的字节数;若出错,返回-1
其返回值通常与参数nbytes值相同,否则表示出错。write出错的一个常见原因是磁盘已写满,或者超过了一个给定进程的文件长度限制。
对于普通文件,写操作从文件的当前偏移量处开始。如果在打开文件时,制定了O_APPEND选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后,该文件偏移量增加实际写的字节数。
3.9 I/O的效率
Page 58 示例:只使用read和write函数复制一个文件。
#include "apue.h"
#define BUFFSIZE 4096
int main(void)
{
int n;
char buf[BUFFSIZE];
while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if(write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");
if(n < 0)
err_sys("read error");
exit(0);
}
关于该程序应注意以下几点:
- 它从编撰输入读,写至标准输出,这就假定在执行本程序之前,这些标准输入、输出已由shell安排好。
- 考虑到进程终止时,UNIX系统内核会关闭进程的所有打开的文件描述符,所以此程序并不关闭输入和输出文件。
- 对UNIX系统而言,文本文件和二进制代码文件并无区别,所以本程序对这两种文件都有效。
我们还没有回答的一个问题是如何选取BUFFSIZE值。使用本程序在ext4文件系统上(磁盘块长度为4096字节),读516581760字节的结果如下:
CPU时间最小值出现在4096及以后的位置,继续增加缓冲区长度对此时间机会没有影响。
大多数文件系统为改善性能都采用某种预读技术,当检测到正进行顺序读取时,系统就试图读入比应用所要求的更多数据,并假象应用很快就会读这些数据。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。