Linux文件和目录操作函数总结

01-文件IO

1
2
3
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

open/close

  • 函数原型:

    • int open(const char *pathname, int flags);
    • int open(const char *pathname, int flags, mode_t mode);
  • 参数:

    • flags

      • 必选项 O_RDONLY, O_WRONLY, O_RDWR

      • 可选项

        • 创建文件: O_CREAT

          • 创建文件时检测文件是否存在: O_EXCL
          • 如果文件存在, 返回-1
          • 必须与O_CREAT一起使用
        • 追加文件: O_APPEND

        • 文件截断: O_TRUNC

        • 设置非阻塞: O_NONBLOCK

    • mode – 指定0777

      • 八进制数

      • 最终权限: mode & ~umaks

      • umask 0002

        • 000000010
        • ~
        • 111111101
        • 111111111
        • &
        • 111111101
        • 775

read

  • 函数原型: ssize_t read(int fd, void *buf, size_t count);

    • 参数:

      • fd – open的返回值
      • buf - 缓冲区, 存放读取的数据
      • count – 缓冲区的最大容量 sizeof(buf)
    • 返回值:

      • -1: 失败
      • >0: 读出的字节数
      • =0: 文件读完了

write

  • 函数原型: ssize_t write(int fd, const void *buf, size_t count);

    • 参数:

      • fd: 文件描述符, open 返回值
      • buf: 要往文件中写的数据
      • count: 有效数据的长度
    • 返回值:

      • -1: 失败
      • >0: 写入的字节数

lseek

  • 函数原型: off_t lseek(int fd, off_t offset, int whence);

    • SEEK_SET
    • SEEK_CUR
    • SEEK_END
  • 使用:

    • 文件指针移动到头部:
    • lseek(fd, 0, SEEK_SET);
  • 获取文件指针当前的位置:

    • int len = lseek(fd, 0, SEEK_CUR);
  • 获取文件长度:

    • int len = lseek(fd, 0, SEEK_END);
  • 文件拓展

    • 文件原大小100k, 拓展为1100k
    • lseek(fd, 1000, SEE_END);

    • 最后做一次写操作write(fd, “a”, 1);

阻塞和非阻塞

  • 阻塞和非阻塞是文件的属性还是read函数的属性?

    • 文件的属性

    • 普通文件:hello.c

      • 默认不阻塞
    • 终端设备:/dev/tty

      • 默认阻塞
      • 管道
      • 套接字

02-stat/lstat函数

获取文件属性

1
2
3
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
  • st_mode – 16位整数

  • 0-2 bit – 其他人权限

    • S_IROTH 00004 读权限
    • S_IWOTH 00002 写权限
    • S_IXOTH 00001 执行权限
    • S_IRWXO 00007 掩码, 过滤 st_mode中除其他人权限以外的信息
    • 3-5 bit – 所属组权限
      • S_IRGRP 00040 读权限
      • S_IWGRP 00020 写权限
      • S_IXGRP 00010 执行权限
      • S_IRWXG 00070 掩码, 过滤 st_mode中除所属组权限以外的信息
    • 6-8 bit – 文件所有者权限
      • S_IRUSR 00400 读权限
      • S_IWUSR 00200 写权限
      • S_IXUSR 00100 执行权限
      • S_IRWXU 00700 掩码, 过滤 st_mode中除文件所有者权限以外的信息
    • 12-15 bit – 文件类型
      • S_IFSOCK 0140000 套接字
      • S_IFLNK 0120000 符号链接(软链接)
      • S_IFREG 0100000 普通文件
      • S_IFBLK 0060000 块设备
      • S_IFDIR 0040000 目录
      • S_IFCHR 0020000 字符设备
      • S_IFIFO 0010000 管道
      • S_IFMT 0170000 掩码,过滤 st_mode中除文件类型以外的信息(st_mode & S_IFMT) == S_IFREG
  • int stat(const char path, struct stat buf);

  • int lstat(const char path, struct stat buf);

    • lstat读取的链接文件本身的属性
    • stat读取的是连接文件指向的文件的属性

      • 追踪,穿透

03-文件属性函数

测试当前用户指定文件是否具有某种属性

  • 当前用户, 使用哪个用户调用这个函数, 这个用户就是当前用户

  • int access(const char *pathname, int mode);

    • 参数:
      • pathname: 文件名
      • mode: 4种权限
      • R_OK – 读
      • W_OK – 写
      • X_OK – 执行
      • F_OK – 文件是否存在
    • 返回值:
    • 0 - 有某种权限, 或者文件存在
    • 1 - 没有, 或文件不存在

修改文件权限

  • int chmod(const char *filename, int mode);

      • 参数:

        • filename: 文件名
        • mode: 文件权限, 八进制数

修改文件所有者和所属组

  • int chown(const char *path, uid_t owner, gid_t group);

    • 函数参数:

      • path – 文件路径

      • owner – 整形值, 用户ID

        • /etc/passwd
      • group – ….., 组ID

        • /etc/group

修改文件大小

  • int truncate(const char *path, off_t length);

  • 参数:

    • path – 文件名
    • length – 文件的最终大小
      • \1. 比原来小, 删掉后边的部分
      • \2. 比原来大, 向后拓展

04-目录操作相关函数

  1. 文件重命名

  • int rename(const char oldpath, const char newpath);
  1. 修改当前进程(应用程序)的路径 cd

  • int chdir(const char *path);

    • 参数: 切换的路径
  1. 获取当前进程的工作目录 pwd

  • char getcwd(char buf, size_t size);

    • 返回值:

      • 成功: 当前的工作目录
      • 失败: NULL
    • 参数:

      • buf: 缓冲区, 存储当前的工作目录
      • size: 缓冲区大小
  1. 创建目录 mkdir

  • int mkdir(const char *pathname, mode_t mode);

    • 参数:
      • pathname: 创建的目录名
      • mode: 目录权限, 八进制的数, 实际权限: mode & ~umask
  1. 删除一个空目录

  • int rmdir(const char *pathname);

    • 参数: 空目录的名字

05-目录遍历相关函数

  1. 打开一个目录

    • DIR opendir(const char name);

      • 参数: 目录名
      • 返回值: 指向目录的指针
    • FILE* fp = fopen()

    • fread(buf, len, len,fp);

  2. 读目录

    1
    2
    3
    4
    5
    6
    7
    8
    struct dirent
    {
    ino_t d_ino; // 此目录进入点的inode
    ff_t d_off; // 目录文件开头至此目录进入点的位移
    signed short int d_reclen; // d_name 的长度, 不包含NULL 字符
    unsigned char d_type; // d_name 所指的文件类型
    har d_name[256]; // 文件名
    };
  • d_type

    • DT_BLK - 块设备
    • DT_CHR - 字符设备
    • DT_DIR - 目录
    • DT_LNK - 软连接
    • DT_FIFO - 管道
    • DT_REG - 普通文件
    • DT_SOCK - 套接字
    • DT_UNKNOWN - 未知
  • struct dirent readdir(DIR dirp);

    • 参数: opendir的返回值
    • 返回值: 目录项结构体
  1. 关闭目录

    • int closedir(DIR *dirp);
  2. 独立完成递归读目录中指定类型文件个数的操作.

06-dup-dup2-fcntl

  1. 复制文件描述符

    • int dup(int oldfd);

      • oldfd - 要复制的文件描述符

      • 返回值: 新的文件描述符

      • dup调用成功:

        • 有两个文件描述符指向同一个文件
      • 返回值: 取最小的且没被占用的文件描述符

    • int dup2(int oldfd, int newfd);

      • oldfd -》hello

      • newfd -》world

        • 假设newfd已经指向了一个文件,首先断开close与那个文件的链接,newfd指向oldfd指向的文件

          • 文件描述符重定向
          • oldfd和newfd指向同一个文件
        • newfd没有被占用,newfd指向oldfd指向的文件
  2. 改变已经打开的文件的属性: fcntl

  • 变参函数

  • 复制一个已有的文件描述符

1
int ret = fcntl(fd, F_DUPFD);
  • 获取/设置文件状态标志

    • open 的flags参数
  1. 获取文件状态标识
1
int flag = fcntl(fd, F_GETFL)
  1. 设置文件状态标识
  • flag = flag | O_APPEND;
  • fcntl(fd, F_SETFL, flag)

  • 可以更改的几个标识: O_APPEND、O_NONBLOCK (常用)


文章结束了,但我们的故事还在继续
坚持原创技术分享,您的支持将鼓励我继续创作!