第三章 文件IO

  • 对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数

    文件描述符 标准 符号常量
    文件描述符0 标准输入 STDIN_FILENO
    文件描述符1 标准输出 STDOUT_FILENO
    文件描述符2 标准错误 STDERR_FILENO
  • 函数open和openat---打开文件

    int open(const char *path, int oflag, .../*mode_t mode*/)
    
    int openat(int fd,const char *path, int oflag, .../*mode_t mode*/)
            两函数的返回值:若成功,返回文件描述符,若出错,返回-1
    
    • path---要打开或创建文件的名字
    • oflag---用来说明此函数的多个选项
    • fd---把open和openat函数区分开,有下列三种情况
      1. path参数指定的是绝对路径名,在这种情况下,fd参数被忽略,openat函数相当于open
      2. path参数指定的是相对路径名,fd参数指出了相对路径名在文件系统中的开始地址。fd参数是通过打开相对路径名所在的目录来获取
      3. path参数指定的是相对路径名,fd参数具有特殊值AT_FDCWD。在这种情况下,路径名在当前工作目录中获取,openat函数在操作上和open函数相似
  • 函数creat---创建文件

    int creat(const char *path, mode_t mode)
        返回值:若成功,返回为只写打开的文件描述符。若出错,返回-1
    
  • 函数close---关闭文件

    int close(int fd)
        返回值:若成功,返回0。若出错,返回-1
    
    • 关闭一个文件时会释放该进程加在改文件上的所有记录锁
  • 函数lseek---显示地为一个打开文件设置偏移量

    off_t lseek(int fd, off_t offset, int whence)
        返回值:若成功,返回新的文件偏移量。若出错,返回-1
    

    对参数offset的解释和参数whence的值有关

    • 若whence = SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节
    • 若whence = SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,offset可正可负
    • 若whence = SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负
  • 函数read---读数据

    ssize_t read(int fd, void *buf,size_t nbytes)
        返回值:读到的字节数,若已到文件尾,返回0。若出错,返回-1
    
    • 有多种情况可使实际读到的字节数少于要求读的字节数
  • 函数write---写数据

    ssize_t write(int fd, const void *buf,size_t nbytes)
        返回值:若成功,返回已写的字节数。若出错,返回-1
    
  • 单个进程打开文件时内核数据结构图

第三章 文件IO_第1张图片
image
  • 两个独立进程各自打开了同一个文件,有如下关系图
第三章 文件IO_第2张图片
image
  • 多个进程读取同一文件都能正常工作。每个进程都有它自己的文件表项,其中也有它自己的当前文件偏移量。但是,当多个进程写同一个文件时,则可能产生预想不到的结果

  • 原子操作指的是由多步组成的一个操作,如果原子操作被执行,要么执行完所有步骤,要么一步也不执行,不可能执行所有步骤中的一个子集

  • 函数dup和dup2---复制一个现有的文件描述符

    int dup(int fd)
    
    int dup2(int fd,int fd2);
        返回值:若成功,返回新的文件描述符。若出错,返回-1
    
    • fd---将要复制的文件描述符
    • fd2---指定新描述符的值(将要返回的)
    • dup返回的新文件描述符一定是当前可用文件描述符中的最小数值
    • dup2是一个原子操作,
    close(fd2);
    fcntl(fd,F_DUPFD,fd2);
    
  • 函数fcntl---改变打开已经打开的文件的属性

    int fcntl(int fd, int cmd, .../* int arg */)
        返回值:若成功,则依赖于cmd。若出错,返回-1
    
    • fcntl有以下5中功能
      • 复制一个已有的描述符(cmd = F_DUPFD 或 F_DUPFD_CLOEXEC)
      • 获取/设置文件描述符标志(cmd = F_GETFD 或 F_SETFD)
      • 获取/设置文件状态标志(cmd = F_GETFL 或 F_SETFL)
      • 获取/设置异步I/O所有权(cmd = F_GETOWN 或 F_SETOWN)
      • 获取/设置记录锁(cmd = F_GETLK、F_SETLK 或 F_SETLKW)
    • 在修改文件描述符标志或文件状态标志时必须谨慎,先要获得现在的标志值,然后按照期望修改,最后设置新标志值。不能只执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位

你可能感兴趣的:(第三章 文件IO)