基础IO(LINUX)

一、C文件接口

1.C默认会打三个输入输出流,分别是stdin,stdout,stderr,对应的文件描述符分别是1,2,3。
2.这三个流的类型都是FILE*,fopen返回值类型,文件指针;

二、接口介绍

OPEN:
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>

  int open(const char *pathname,int flags);
  int open(const char *pathname,int flags,mode_t mode);

pathname: 要打开或创建的目标文件。
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

参数:

  • O_RDONLY: 只读打开
  • O_WRONLY: 只写打开
  • O_RDWR: 读,写打开
  • (这三个常量,必须指定一个且只能指定一个 )
  • O_CREAT: 若文件不存在,则创建。需要使用mode选项,来指明新文件的访问权限
  • O_APPEND: 追加写

返回值:

  • 成功:新打开的文件描述符
  • 失败:-1

三、系统调用和库函数

库函数(C标准库中的函数):fopen fclose fread fwrite ……
系统调用接口:open close read write lseek ……
库函数和系统调用接口是上下级的关系
可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发

在这里插入图片描述
注:fopen,fclose等f系列的库函数一般在用户操作接口中的lib中

四、文件描述符

LINUX下,一切皆文件
LINUX进程默认情况下有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2
0,1,2对应的物理设备一般是:键盘,显示器,显示器

在这里插入图片描述
理解:

  • 进程执行open系统调用的时候,进程和文件的关系一般是一对多的关系,一个进程中可以打开多个文件。当打开文件时,操作系统在内存中创建相应的数据结构来描述目标文件,我们把它称为file结构体,表示一个已经打开的文件。为了将进程和文件联系起来,因此每个进程中都有一个*files指针,这个指针指向一个files_struct表,这个表中包含一个指针数组,数组中的每个元素都是一个指向打开文件的指针,因此文件描述符本质上就是该数组的下标,通过文件描述符就可以找到对应文件。

文件描述符的分配规则:从最小的未被使用的文件描述符开始分配

重定向:
在这里插入图片描述
理解:

  • 当关闭标准输出时,myfile的地址将会被写在文件描述符为1的位置,而printf函数是C库中的IO函数,一般往stdout输出,而stdout底层访问文件时,找的是文件描述符为1的位置,因此此时已经是myfile的地址,所以将内容写到了myfile文件中,而没有写进显示器地址中,完成了输出重定向。

五、FILE

因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上访问文件都是通过fd访问的,因此C库当中的FILE结构体内部必定封装了fd
在这里插入图片描述
运行结果:
hello printf
hello fwrite
hello write
但如果对进程实现重定向,./hello > file,结果为:
hello write
hello printf
hello fwrite
hello printf
hello fwrite
造成结果不同的原因为:

  • 首先了解缓冲方式分为三种:无缓冲,行缓冲(显示器),全缓冲(硬盘)
  • ptintf和fwrite是库函数,会自带缓冲区,数据缓冲方式为行缓冲,但当重定向到文件后,缓冲方式会变为全缓冲,放在缓冲区的数据不会立即刷新,而是等待进程结束后统一刷新
  • fork( )创建子进程,父子进程要发生写时拷贝,因此父进程准备刷新时,子进程也有一份同样的数据,因此产生两份数据
  • write没有输出两次,表明write不带缓冲区库函数是系统调用的“上层”,是对系统调用的封装,而write没有缓冲区,但printf、fwrite有缓冲区,因此缓冲区是二次加上的,由C标准库提供

六、文件系统

权限:可读、可写、可执行、粘滞位
文件包括文件内容和文件属性
inode: 保存文件属性

  • 通常情况下一个文件有一个inode
  • 一个inode有一个inode号
  • 文件名和inode之间有映射关系

查找文件步骤:inode号 -> inode -> 数据块 -> 数据
LINUX中操作任何文件都是在特定目录下操作,目录也是文件,所以目录里面必定包含文件名和文件名与inode号之间的映射关系
硬链接:硬链接没有独立的inode号 硬链接是文件名和inode号之间的映射关系
软链接:软链接有独立的inode号 软链接是一个独立的目标文件 软链接里面放了目标文件所在的路径和内容

注:

  1. 若有一个三级目录,dir dir1 dir2
  2. 则dir的硬链接数为3:dir和它本身inode号的映射关系 +dir和它当前目录的映射 + dir和下级目录dir1的映射
  3. dir1的硬链接数为3:dir1和本身inode号的映射 +dir1和它当前目录的映射 + dir1和下级目录dir2的映射
  4. dir2的硬链接数为2:dir2和本身inode号的映射 +dir2和当前目录的映射

文件的三个时间:

  • Access 最后访问的时间
  • Modify 文件内容最后修改的时间
  • Change 属性最后修改的时间

猜你喜欢

转载自blog.csdn.net/D_4_Y_/article/details/88523969