• 【Linux_Unix系统编程】chapter5 深入探究文件IO


    Chapter5 深入探究文件I/O
    本章节将介绍另一个与文件操作相关的系统调用:多用途的fcntl(),并展示其应用之一读取和设置打开文件的状态标志。

    5.1 原子操作和竞争条件
    所有系统调用都是以原子操作方式执行的。是以为内核保证了某系统调用中的所有步骤会作为独立操作而一次性加以执行,其间不会为其他进程或线程所中断。

    以独占方式创建一个文件:
    当同时制定O_EXCL与O_CREAT作为open()标志位时,如果要打开的文件已存在,则open()将返回一个错误。保证了进程是打开文件的创建者。

    向文件尾部追加数据:
    多个进程同时向同一个文件尾部添加数据。

    5.2 文件控制操作:fcntl()
    fcntl()系统调用对一个打开的文件描述符执行一系列控制操作。
    #include <fcntl.h>
    int fcntl(int fd, int cmd, …);

    5.3 打开文件的状态标志
    fcntl()的用途之一是针对一个打开的文件,获取或修改其访问模式和状态标识。
    int flags, accessMode;
    flags = fcntl(fd, F_GETFL);
    if(flags = -1)
    errExit(“fcntl”);
    在上述代码之后,可以以如下代码测试文件是否以同步写方式打开:
    if(flags & O_SYNC)
    printf(“wirtes are synchronize ”);

    5.4 文件描述符和打开文件之间的关系
    进程级的文件描述符表
    系统级的打开文件表
    文件系统的i-node表
    5.5 复制文件描述符
    dup()调用复制一个打开的文件描述符oldfd,并返回一个新描述符。二者指向同一打开的文件句柄。
    #include <unistd.h>
    int dup(int oldfd);

    5.6 在文件特定偏移量处的I/O:pread()和pwrite()
    系统第阿勇pread()和pwrite()完成与read和write()相似的工作,只是前两者会在offset参数所指定的位置进行文件IO操作,而非始于文件的当前偏移量楚,且他们不会修改文件的当前你偏移量。
    #include <unistd.h>
    ssize_t pread(int fd, void *buf, size_t count, off_t offset);
    ssize_t pwirte(int fd, const void *buf, size_t count, off_t offset);

    pread()调用等价于如下调用纳入同一原子操作:
    off_t orig;
    orig = lseek(fd, 0,SEEK_CUR);
    lseek(fd, offset, SEEK_SET);
    s = read(fd, buf, len);
    lseek(fd, origin, SEEK_SET);

    5.7 分散输入和集中输出(Scatter-Gather I/O):readv()和writev()
    #include <sys.uio.h>
    ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
    ssize_t wirtev(int fd, const struct iovec *iov, int iovcnt);
    这些系统调动并非只是对单个缓冲区进行读写操作,而是一次即可传输多个缓冲区。数组iov定义一组用来传输数据的缓冲区。整数iovcnt则指定了iov的成员个数。iov中的每个成员都是如下形式的数据结构。
    struct iovec
    {
    void *iov_base;
    size_t iov_len;
    }

    5.8 截断文件:truncate()和ftruncate()系统调用
    truncate()和ftruncate()系统调用将文件打下设置为length参数指定的值。
    #include <unistd.h>
    int truncate(const char* pathname, off_t length);
    int ftruncate(int fd, off_t length);
    若文件当前长度大于参数length,调用将丢弃超出部分,若小于参数length,调用将在文件尾部添加一系列空字节或者是一个文件空洞。

    5.9 非阻塞I/O
    在打开文件是指定O_NONBLOCK标志,目的有二:
    (1):若open()调用未能立即打开文件,则返回错误,而非陷入阻塞。
    (2):调用open()成功后,后续的I/O操作也是非阻塞的。
    管道,FIFO,套接字,设备都支持非阻塞模式。

    5.10 大文件I/O
    过渡性LFS API
    要使用过渡性的LFS API,必须在编译程序时定义 LARGEFILE64_SOURCE功能测试宏。 fopen64(),open64(),lseek64(),truncate64(),stat64(),mmap64()和setrlimit64().
    调用open64(),相当于在调用open()是指定O_LARGEFILE标志。

    5.11 /dev/fd 目录
    对于每个进程,内核都提供有一个特殊的虚拟目录/dev/fd.该目录中包含”/dev/fd/n”形式的文件名,其中n是与进程中的打开的文件描述符相对应的编号。例如:/dev/fd/0 就对应于进程的标准输入。
    e.g.:如下等价,相当于复制相应的文件描述符。
    fd = open(“/dev/fd/1”, O_WRONLY);
    fd = dup(1)

    5.12 创建临时文件
    mkstemp()和tmpfile()
    基于调用者提供的模板,mkstemp()函数生成一个唯一文件名并打开该文件,返回一个可用于I/O调用的文件描述符。
    #include <stdlib.h>
    int mkstemp(char *template);
    模板参数采用路径形式,其中最有6个字符必须是XXXXXX。
    int fd;
    char template[] = “/tmp/somestringXXXXXX”;
    fd = mkstemp(template);
    if(fd == -1)
    errExit(“mkstemp”);
    unlink(template);

    tmpfile()函数会创建一个名称唯一的临时文件,并以读写方式将其打开。
    #include <stdio.h>
    FILE *tmpfile(void);

    作者:长风 Email:844064492@qq.com QQ群:607717453 Git:https://github.com/zhaohu19910409Dz 开源项目:https://github.com/OriginMEK/MEK 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 感谢您的阅读。如果觉得有用的就请各位大神高抬贵手“推荐一下”吧!你的精神支持是博主强大的写作动力。 如果觉得我的博客有意思,欢迎点击首页左上角的“+加关注”按钮关注我!
  • 相关阅读:
    #动态规划 0-1背包问题空间复杂度优化
    #动态规划 0-1背包问题思路概述
    #动态规划 LeetCode 337 打家劫舍 III
    #动态规划 LeetCode 213 打家劫舍 II
    #动态规划 LeetCode 198 打家劫舍
    #动态规划 LeetCode 63 不同路径 II
    #动态规划 LeetCode 62 不同路径
    #动态规划 LeetCode 279 完全平方数
    #动态规划 LeetCode 343 整数拆分
    #动态规划 LeetCode 64 最小路径和
  • 原文地址:https://www.cnblogs.com/zhaohu/p/8048044.html
Copyright © 2020-2023  润新知