TLPI读书笔记第4章-文件IO1

4.1 概述

所有执行 I/O 操作的系统调用都以文件描述符,一个非负整数(通常是小整数),来指代打开的文件。文件描述符用以表示所有类型的已打开文件,包括管道(pipe)、 FIFO、 socket、终端、设备和普通文件。针对每个进程,文件描述符都自成一套。

执行文件 I/O 操作的 4 个主要系统调用

4.1.1 open

fd = open(pathname, flags, mode) 函数打开 pathname 所标识的文件,并返回文件描述符,用以在后续函数调用中指代打开的文件。如果文件不存在, open()函数可以创建之,这取决于对位掩码参数 flags 的设置。 flags 参数还可指定文件的打开方式:只读、只写亦或是读写方式。 mode 参数则指定了由 open()调用创建文件的访问权限,如果 open()函数并未创建文件,那么可以忽略或省略 mode 参数。

4.1.2 read

numread = read(fd, buffer, count) 调用从 fd 所指代的打开文件中读取至多 count 字节的数据,并存储到 buffer 中。 read()调用的返回值为实际读取到的字节数。如果再无字节可读(例如:读到文件结尾符 EOF 时),则返回值为 0。

4.1.3 write

numwritten = write(fd, buffer, count) 调用从 buffer 中读取多达 count 字节的数据写入由fd 所指代的已打开文件中。 write()调用的返回值为实际写入文件中的字节数,且有可能小于 count。

4.1.4 close

status = close(fd)在所有输入/输出操作完成后,调用 close(),释放文件描述符 fd 以及与之相关的内核资源。

复制文件的一个案例fileio/copy.c

#include <sys/stat.h>
#include <fcntl.h>
#include "tlpi_hdr.h"

#ifndef BUF_SIZE        /* Allow "cc -D" to override definition */
#define BUF_SIZE 1024
#endif

int main(int argc, char *argv[])
{
    /* 自定义源文件和目标文件的文件描述符 */
    int inputFd, outputFd, openFlags;
    mode_t filePerms;
    ssize_t numRead;
    char buf[BUF_SIZE];

    if (argc != 3 || strcmp(argv[1], "--help") == 0)
        usageErr("%s old-file new-file
", argv[0]);

    /* 打开源文件和目标文件 */

    inputFd = open(argv[1], O_RDONLY);
    if (inputFd == -1)
        errExit("opening file %s", argv[1]);

    openFlags = O_CREAT | O_WRONLY | O_TRUNC;
    filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
                S_IROTH | S_IWOTH;      /* rw-rw-rw- */
    outputFd = open(argv[2], openFlags, filePerms);
    if (outputFd == -1)
        errExit("opening file %s", argv[2]);

    /** 将从源文件读到的数据写入目标文件
     * read的返回值等于实际读到的字节数,到再无可读,numRead=0
     * write的返回值等于实际写入字节数,不一定等于numRead
     * 以下两种情况会退出
     * 1.读写到末尾
     * 2.出现错误
     * 关闭inputFD/outputFD失败都会返回-1
     * */

    while ((numRead = read(inputFd, buf, BUF_SIZE)) > 0)
        if (write(outputFd, buf, numRead) != numRead)
            fatal("write() returned error or partial write occurred");
    if (numRead == -1)
        errExit("read");

    if (close(inputFd) == -1)
        errExit("close input");
    if (close(outputFd) == -1)
        errExit("close output");

    exit(EXIT_SUCCESS);
}
原文地址:https://www.cnblogs.com/wangbin2188/p/14627368.html