文件与进程

avatar
作者
猴君
阅读量:0

理解文件:

操作文件的本质是进程在操作文件!这是进程和文件的关系!

如何理解文件?

文件在未打开之前是存在磁盘中的,而磁盘是在外设上的,也就是硬件上的,所以向文件中写入,本质上就是在朝硬件中写入,但是用户并没有权力直接在硬件上进行写入操作,所以必须通过操作系统进行写入,所以使用fopen、fwr、fprintf等等,其实本质上都是一个操作系统的调用函数,是C语言库对操作系统提供的系统调用函数的一种封装,同时C/C++等其他语言访问文件的方式有些不一样!

文件操作:

open:打开文件

  • 第一个参数是文件名或者文件路径,只有文件名则是表示打开的文件在当前的路劲下
  • 第二个参数是表示这么创建这个文件,表示一个整数,能使用很多标记为

标记位的使用:

标记位是 以写方式打开,如果没有则创建,如果fd获取的标记为是小于0则表示文件打开失败!

创建了这个文件,而这个文件创建出来的权限不对劲!在Linux中,如果创建文件,就要设置这个文件的初始权限,所以这就需要第三个参数来赋予文件的权限!同时权限也是一个整数

0666表示的就是一个文件的读写权限

不过为什么这个文件的权限是664而我们赋予的是666,这是系统中存在的一个权限掩码,这是系统将权限掩码和我们赋予的权限进行了位运算,这个权限掩码是可以进行更改的!

使用umask函数将权限掩码变成0,这样就可以把文件的权限设置成我们想要的权限了!注意权限掩码默认是002为什么open的第二个参数是整数,那为什么我们写的全是字符?

一个整数是由32位比特位写的 ,所以使用比特位来进行标志位的传递,这是操作系统对很多系统调用接口的一种常见方式!而我们在第二个参数上写的字符,其实是以比特位来设计的一种宏!

 关闭文件:
 

 

写入文件:

 

文件描述符 fd:

是以上文件函数的 第一个参数 ,同时也是打开文件失败的返回值!并不是从0、1、2开始进行返回值的,而是从3开始,而0、1、2分别是标准输入、标准输出、标准错误

0、1、2是系统开启后默认打开的,同样也可以被使用:

操作系统要为被打开的文件进行管理,所以每次打开一个文件 操作系统就会形成一个关于这个文件的内核数据结构struct file ,这个内核数据结构会拥有关于该文件的属性,例如文件的打开方式。

而对于文件的管理就是对struct file 的管理,而一群struct file 结构体 会进行双链表链接,同时每一个文件都会拥有操作系统为文件申请的一个内存,也就是文件按内核级的缓存区

所以最后,文件的属性是用来进行struct file 的初始化,而文件的内容则是存放在文件内核级缓存区中,每次的修改的内容都会在缓存区中存放,并由缓存区冲刷到文件所在的磁盘中进行修改,而读取文件内容则是文件将内容拷贝到缓存区中

所以无论读写都必须让操作系统把文件的内容读取到缓存区当中!所以对于文件的修改是内核级的,而不是磁盘级的

而对于打开文件的本质是打开进程,进程可以打开多个文件,所以进程对文件的关系是一对多,那进程如何找到它自己打开的文件呢

在进程task_strucrt 的属性中具有一个struct files_struct *file 的数据数据结构,正是使用了这个结构体,才让进程和文件建立了关系

struct files_struct *file 的内部存在一个数组,且是一个指针数组,这个指针数组内部的指针指向的就是文件,同时数组的0、1、2下标存储的是标准输入、标准输出、标准错误

同时文件的地址一一被struct files_struct *file内部的指针指向,并存放在了这个数组的内部,而这个数组的下标最终会被拿取,变成 文件描述符,所以fd的本质就是这个数组的下标,通过这个下标来获取文件的信息和内容 

open是在创建file 和开辟文件缓存区的空间,加载文件数据,进行查找进程的文件缓存区的表,把file的地址填入对应的表内,最后返回数组下标

 那为什么fd 0、1、2会默认打开?

因为0、1、2是硬件!而对于Linux中一切皆文件!所以硬件也是文件!

而对于一切皆文件如何理解?

对于每一个设备而言,都具有名字、类别、厂商、操作方法等属性

因此每一个操作系统都可以被一个结构体所描述:

同时每一个文件 的 struct file 内部都具有相对应的读写指针,而每一个硬件设备的驱动内都有读写操作方法实现,虽然每一个硬件设备的读写操作实现方法都是不一样的,但是可以设置成一样类型的,所以文件中的struct file内部的读写指针可以一一指向和对应硬件驱动上的读写操作方法!

而对与每一个被打开的文件来说,它的读、写指针是struct file 内部的一块新的属性,也是每一个被打开文件的操作底层!

所以,只需要看struct file 内部的读写指针指向那个硬件的读写方法,就表示这个文件访问了这个硬件!所以这就是一切皆文件!在操作系统内部,系统在访问文件的时候只认文件描述符fd!

而对于C语言C++的文件操控函数,例如fopen、fcolose等 为什么需要使用FLIE作为类型指针,这是因为FILE是一个C语言提供的结构体,而在这个结构体的内部一定是要封装fd 的! 所以所有C语言上的文件操作函数,本质底层都是系统调用的封装!

C语言为什么要这样做?

C语言可以使用系统调用,也可也使用语言层面上提供的文件方法,这主要是因为操作系统的不同,系统调用的函数可能不一样,而C语言是一个能够跨平台的语言,所以可以直接使用C语言的方法。

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!