Linux的I/O文件系统

1.在 Linux 系统中,内核会为每个进程(关于进程的概念,这是后面的内容,我们可以简单地理解为一个运行的程序就是一个进程,运行了多个程序那就是存在多个进程)设置一个专门的数据结构用于管理该进程,譬如用于记录进程的状态信息、运行特征等,我们把这个称为进程控制块(Process control block,缩写PCB)。PCB 数据结构体中有一个指针指向了文件描述符表(File descriptors),文件描述符表中的每一个元素索引到对应的文件表(File table),文件表也是一个数据结构体,其中记录了很多文件相关的信息,譬如文件状态标志、引用计数、当前文件的读写偏移量以及 i-node 指针(指向该文件对应的 inode)等,进程打开的所有文件对应的文件描述符都记录在文件描述符表中,每一个文件描述符都会指向一个对应的文件表
2.在这里插入图片描述

3.errno:返回错误处理的编号
4.Strerror() 函数:将对应的 errno 转换成适合我们查看的字符串信息
5.perror ()函数:此函数不需要传入 errno,函数内部会自己去获取 errno 变量的值,调用此函数会直接将错误提示字符串打印出来,而不是返回字符串。(这个用的多)
6._exit()和_Exit()函数,exit()函数都是终止进程用的,其中_exit()和_Exit()函数属于linux系统调用,exit()属于c库调用。
7.空洞文件的概念:有逻辑大小和实际大小之分。比如一个文件,头地址开始有2k的数据,24k没有数据,46k又有数据,我们可以看到中间空了一部分。他的逻辑大小是6k,实际大小为4k。
8.O_TRUNC :这个标志的作用非常简单,如果使用了这个标志,调用 open 函数打开文件的时候会将文件原本的内容全部丢弃,文件大小变为 0;
9.O_APPEND当每次使用 write()函数对文件进行写操作时,都会自动把文件当前位置偏移量移动到文件末尾,从文件末尾开始写入数据,也就是意味着每次写入数据都是从文件末尾开始。
10.重复打开同一个文件,进行写操作,譬如一个进程中两次调用 open 函数打开同一个文件,分别得到两个文件描述符 fd1 和 fd2,使用这两个文件描述符对文件进行写入操作,那么它们是分别写(各从各的位置偏移量开始写)还是接续写(一个写完,另一个接着后面写)?因为这两个文件描述符所对应的读写位置偏移量是相互独立的,所以是分别写。要实现多个打开接续写,那就用O_APPEND打开两个文件,再写入即可。重复打开多个文件,只会存在一个动态文件。
在这里插入图片描述

11.dup 函数:dup 函数用于复制文件描述符,同时打开的时候,可以实现接续写的功能。缺点是并不能自己指定一个文件描述符。
12.Dup2 函数:用于复制文件描述符,优点是可以指定想要的文件描述符。
13.文件共享:文件共享,就是上面提到的同时打开多个文件,同时对文件进行读写操作。存在以下三种情况:
13.1同一个进程中多次调用 open 函数打开同一个文件。
13.2不同进程中分别使用 open 函数打开同一个文件。
13.3同一个进程中通过 dup(dup2)函数对文件描述符进行复制。
14.竞争冒险:当一个文件被多次打开的时候,如果存在多个进程对文件进行操作,可能会导致不同进程写入的内容被相互覆盖或者是其他问题。因为一个进程对文件进行操作时,有3个步骤,一个是打开文件,二是系统调用lseek 函数确定偏移量,三是写入。这里存在的问题是第二第三步是分开的,如果进程A到完成第二步时时间片耗尽了,然后别的进程B此时可能对文件写入新的内容,然后进程B时间片耗尽时,进程A又可以继续第三步骤,但此时进程A可能会把进程B写的内容覆盖掉。
15.原子操作:所谓原子操作,是有多步操作组成的一个操作,原子操作要么一步也不执行,一旦执行,必须要执行完所有步骤,不可能只执行所有步骤中的一个子集。也就是不管时间片是否耗尽,都要执行完。
原子操作的方法:
15.1O_APPEND 实现原子操作:O_APPEND 的一个非常重要的作用,那就是实现原子操作,移动当前写位置偏移量到文件末尾、写入数据”这两个操作步骤就组成了一个原子操作。不管怎么写入数据都会是从文件末尾写,这样就不会导致出现“进程 A 写入的数据覆盖了进程 B 写入的数据”这种情况了。
15.2pread()和 pwrite():可用于实现原子操作,调用 pread 相当于调用 lseek 后再调用 read;同理,调用 pwrite相当于调用 lseek 后再调用 write。特点是:调用 pread 或pwrite时,无法中断其定位和读操作(也就是原子操作)且不更新文件表中的当前位置偏移量。
15.3: O_EXCL:创建文件时也会有竞争冒险的情况,比如A进程创建了一个文件,然后进程A时间片结束,进程B如果此时又创建一个新的文件,那将是不被允许的。所以,我们就在open函数中用O_EXCL标志。O_EXCL 可以用
于测试一个文件是否存在,如果不存在则创建此文件,如果存在则返回错误,这使得测试和创建两者成为一个原子操作。
16.fcntl()函数:可以对一个已经打开的文件描述符执行一系列控制操作,譬如复制一个文件描述符(与 dup、dup2 作用相同)、获取/设置文件描述符标志、获取/设置文件状态标志等。类似于一个多功能文件描述符管理工具箱。
17.Ioctl() 函数:可以认为是一个文件 IO 操作的杂物箱,可以处理的事情非常杂、不统一,一般用于操作特殊文件或硬件外设。
18.截断文件:使用系统调用 truncate()或 ftruncate()可将普通文件截断为指定字节长度.调用这两个函数并不会导致文件读写位置偏移量发生改变,所以截断之后一般需要重新设置文件当前的读写位置偏移量,以免由于之前所指向的位置已经不存在而发生错误。如果文件目前的大小大于参数 length 所指定的大小,则多余的数据将被丢失,类似于多余的部分被“砍”掉如果文件目前的大小小于参数 length 所指定的大小,则将其进行扩展。(使用 ftruncate()函数进行文件截断操作之前,必须调用 open()函数打开该文件得到文件描述符,并且必须要具有可写权限)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值