Linux编程(8)_文件IO

时间:2021-03-31 04:41:57

1 C库IO函数工作流程

Linux编程(8)_文件IO

Linux编程(8)_文件IO

Linux编程(8)_文件IO

Linux编程(8)_文件IO

2 Linux 系统函数

1.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

    • mode & ~umask

      0777&~0002

      111111111

      111111101

      &

      111111101

2.read

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

参数:
- fd : open的返回值
- buf : 缓冲区, 存储要读取的数据
- count : 缓冲区能存放的最大字节数

  • 返回值:
    • -1 : 失败
    • 成功:
    • >0 : 读出的字节数
    • =0 : 文件读完了

3.write

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

      • 参数:
    • fd : open的返回值
      • buf : 要写到文件的数据
      • count : strlen(buf)
      • 返回值:
      • -1 : 失败
      • >0 : 写入到文件的字节数

4.全局变量 errno

当系统函数调用失败, 会自动赋值错误信息.

不同的值对应不同的对应信息.

perror(); 打印错误信息

5.lseek

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

    • SEEK_SET 头部
    • SEEK_CUR 当前位置
    • SEEK_END 尾部
  • 使用

    1. 文件指针移动到头部

      lseek(fd, 0, SEEK_SET);

    2. 获取文件指针当前的位置

      int len = lseek(fd, 0 , SEEK_CUR)

    3. 获取文件长度

      int len = lseek(fd, 0, SEEK_END)

  • 文件扩展

    文件原大小100k, 扩展为1100k lseek(fd, 1000, SEEK_END); 等于把文件指针从尾部往后偏移1000k

    再做一次写操作 write(fd, "a", 1) ,必须这样写一次数据, 随便写什么, 才能成功

    所以不是太好用.

3 阻塞和非阻塞

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

  • 文件的属性
  • 普通文件: hello.c 默认不阻塞
  • 终端设备 /dev/tty 默认阻塞
    • 套接字
    • 管道

4 stat函数介绍

  • 获取文件属性

    1. struct stat {
  • ​ dev_t st_dev; //文件的设备编号

  • ​ ino_t st_ino; //节点

  • ​ mode_t st_mode; //文件的类型和存取的权限

  • ​ nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1

  • ​ uid_t st_uid; //用户ID

  • ​ gid_t st_gid; //组ID

  • ​ dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号

  • ​ off_t st_size; //文件字节数(文件大小)

  • ​ blksize_t st_blksize; //块大小(文件系统的I/O 缓冲区大小)

  • ​ blkcnt_t st_blocks; //块数

  • ​ time_t st_atime; //最后一次访问时间

  • ​ time_t st_mtime; //最后一次修改时间

  • ​ time_t st_ctime; //最后一次改变时间(指属性)

  • };

    • 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读取的是连接文件指向的文件的属性

      • 追踪,穿透