APUE 学习记录 20200628

3.7 函数read

调用read函数从打开文件中读数据。shell

#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函数向打开文件中写数据。spa

#include <unistd.h>
ssize_t write(int fd, void * buf, size_t nbytes); // 返回值:若成功,返回已写的字节数;若出错,返回-1

其返回值一般与参数nbytes值相同,不然表示出错。write出错的一个常见缘由是磁盘已写满,或者超过了一个给定进程的文件长度限制。指针

对于普通文件,写操做从文件的当前偏移量处开始。若是在打开文件时,制定了O_APPEND选项,则在每次写操做以前,将文件偏移量设置在文件的当前结尾处。在一次成功写以后,该文件偏移量增长实际写的字节数。code

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字节的结果以下:
image.pngit

CPU时间最小值出如今4096及之后的位置,继续增长缓冲区长度对此时间机会没有影响。大多数文件系统为改善性能都采用某种预读技术,当检测到正进行顺序读取时,系统就试图读入比应用所要求的更多数据,并假象应用很快就会读这些数据。

相关文章
相关标签/搜索