欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c/c++:文件IO(Linux系统IO、C标准库IO、标准C 库IO和 Linux系统IO的关系、虚拟地址空间)

程序员文章站 2022-06-07 14:28:46
...

目录

一、Linux系统IO和C标准库IO

1.1 标准C库IO函数

1.2 标准C 库IO和 Linux系统IO的关系

二、 虚拟地址空间

三、Linux系统IO函数

四、Linux其他系统函数


 

 

一、Linux系统IO和C标准库IO

1.1 标准C库IO函数

c/c++:文件IO(Linux系统IO、C标准库IO、标准C 库IO和 Linux系统IO的关系、虚拟地址空间)

 

1.2 标准C 库IO和 Linux系统IO的关系

c/c++:文件IO(Linux系统IO、C标准库IO、标准C 库IO和 Linux系统IO的关系、虚拟地址空间)

标准C 库IO:带缓冲区

Linux系统IO:不带缓冲区,(有些书上说Linux系统有缓存,那是内核的缓存,不是IO的缓存)

 

 

 

二、 虚拟地址空间

下图以32位机为例,2的32次方为4G,64位机是2的64次方,太大了不好画。

c/c++:文件IO(Linux系统IO、C标准库IO、标准C 库IO和 Linux系统IO的关系、虚拟地址空间)

 

c/c++:文件IO(Linux系统IO、C标准库IO、标准C 库IO和 Linux系统IO的关系、虚拟地址空间)

文件描述符表默认大小: 1024,每个进程启动之后, 都有一个文件描述符表,所以每个进程默认能打开的文件个数: 1024
前三个文件文件描述符是默认被使用了的:  - 标准输入 -> 0, 标准输出 -> 1, 标准错误 -> 2

除去被占用的每个进程默认能打开的文件个数: 1021

 

三、Linux系统IO函数

 

  • errno -> 属于Linux系统函数库, 库里边的一个全局变量, 记录的是错误号
#include <stdio.h>
void perror(const char *s);           - s参数: 用户描述, 比如:hello

perror打印的是errno对应的错误描述, 实际输出: hello: xxxxx(实际的错误描述)

 

  •  open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
  // open函数
  // 打开一个已经存在文件
  int open(const char *pathname, int flags);
  	参数:
          - pathname: 要打开的文件路径
          - flags: 对文件的操作权限设置
              - O_RDONLY,  O_WRONLY,  O_RDWR 这三个设置是互斥的
       返回值: 
  // 使用open创建一个新文件
  int open(const char *pathname, int flags, mode_t mode);
  	参数: 
  		- pathname: 要打开的文件路径
          - flags: 对文件的操作权限设置
              - 必选项: O_RDONLY,  O_WRONLY,  O_RDWR 这三个设置是互斥的
              - 可选项: O_CREAT -> 文件不存在, 创建新文件
          - mode: 八进制的数, 表示用户对创建出的新文件的操作权限, 比如: 0775, mode & ~umask
          		0777	-> 111111111
          		0775    -> 111111101
          	&	
                  0775       111111101
         按位与: 0和任何数都为0

 

  • close
  #include <unistd.h>
  int close(int fd);

 

  • read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
  	参数: 
  		- fd: open得到的, 通过这个fd操作某一个文件
  		- buf: 缓冲区, 存储读到的数据, 数组的地址
  		- count: buf的大小
  	返回值: 
  		- 成功: 
  			>0: 返回实际读到的字节数
  			==0: 文件已经读完了
  		- 失败: -1

 

  • write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
  	参数: 
  		- fd: open得到的, 通过这个fd操作某一个文件
  		- buf: 要往磁盘写入的数据
  		- count: 要写的数据的实际大小
  	返回值:
  		成功: 实际写入的字节数
  		失败: -1

 

  • lseek
#include <sys/types.h>
#include <unistd.h>

  off_t lseek(int fd, off_t offset, int whence);
  	参数: 
  		- fd: open得到的, 通过这个fd操作某一个文件
  		- offset: 偏移量
  		- whence: 
  			SEEK_SET
                设置文件指针的偏移量
         		SEEK_CUR
                设置偏移量: 当前位置 + 第二个参数的值
         		SEEK_END
                设置偏移量: 文件大小 + 第二个参数的值
  int fseek(FILE *stream, long offset, int whence);
  
  
  // 1. 移动文件指针到文件头
  lseek(fd, 0, SEEK_SET);
  // 2. 获取当前文件指针的位置
  lseek(fd, 0, SEEK_CUR);
  // 3. 获取文件长度
  lseek(fd, 0, SEEK_END);
  // 4. 拓展问长度, 当前文件10b, 110b, 增加的字节的0
  lseek(fd, 100, SEEK_END);
  // 要进行一次写操作
  write(fd, " ", 1);

 

四、Linux其他系统函数

  • stat / lstat
 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: 
  	- 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
  



  #include <sys/types.h>
  #include <sys/stat.h>
  #include <unistd.h>
  int stat(const char *pathname, struct stat *buf);
  	参数: 
  		- pathname: 操作的文件的路径
  		- buf: 结构体变量, 传出
  struct stat st;
  stat("hello.txt", &st); 

stat是一个int类型数据,一个int数据可以表示32位2进制数,具体如下:

c/c++:文件IO(Linux系统IO、C标准库IO、标准C 库IO和 Linux系统IO的关系、虚拟地址空间)

 

  • opendir  目录遍历函数
DIR *opendir(const char *name);
  	参数: 
  		- name: 要打开的目录
  	返回值: DIR * 
  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);
  	- 返回一个结构体, 这个对应一个文件
  int closedir(DIR *dirp);