入职day2(应用开发)

一、文件io基础使用

在Linux 的开发之下,一切皆是为文件。所以常常开发是对文件进行操作的。

常见的文件操作函数有open、write、read、close。

而这些操作函数经常使用一个返回值,我们称之为文件描述符。

1.1打开函数open

在liunx中对一个文件进行操作,首先需要打开文件,得到文件描述符,后续才能进行对该文件进行读写配置。

其函数原型

open(地址,操作标志)

 

详细的内容在系统中使用 man 2 open 指令去查看。

地址参数内容: 需要打开的文件地址,可以是绝对路径或者绝对路径。

操作标志:常用的操作标志有:

 经常输入多个标志参数,使用 (|)符号来完成多个标志的输入

还有一些标志未列举出来。

在三个参数形式,第三个参数表明创建文件的权限,其标志有:

 例子:

fd = open("./app.c", O_RDONLY)
打开目录./app.c  只读的形式,打开成功将会返回一个非0的文件描述符

如果有错误,返回一个负数的整形内容。

1.2 Write 写文件

写文件也可以使用man手册去查找函数的原型

参数讲解:

int fd: 文件描述符,前面打开文件会返回的文件描述符,从文件描述符里面 。

buf:指定写入数据对应的缓冲区, 简单点说就是写入的内容,或者内容做指向的一个缓冲区

count: 制定写入的字节,常用sizeof函数去计算,或者肉眼计算。

返回值: 如果写文件成功,将会返回写入的字节数,如果数字小于count参数,则是磁盘已经满了。如果写入错误则是返回-1

1.3 read读文件

同理,通过man 2 read 手册可以查看其函数原型。

参数的意义与write写文件函数的一样。

1.4 close 关闭文件

其函数原型

 直接调用close 关闭相应的文件标识符。

1.5 lseek 位置偏移量函数

其函数原型

 

fd: 文件描述符

offest: 偏移量  以字节为单位

whence: 用于定义参数offset 偏移量对应的参考值  系统已经定义好了

 

 成功则返回当前读写位置,错误返回-1

 二、深入探究文件IO

2.1 系统如何管理文件

静态文件和inode

文件存放在磁盘文件系统,并且以一种固定的方式来存放,我们称之为静态文件。

在磁盘上,磁盘存储的单位是 “扇区” ,而块则是由连续的8个扇区组成。而静态文件对应的数据则是磁盘设备中的不同 “块” 

实际上:磁盘中有一个inode区,会有一个inode表,这个表则用来存放inode节点,每一个节点都对应了一个文件。其结构如下:

 通过用ls-i命令去查看这个inode 编号。

实际上,我们去open一个文件的时候,内核会申请一段内存,将静态文件的内容从磁盘中读取到内存中进行管理以及缓存。而我们是针对这一段内容中的动态文件进行操作。 而不是操作磁盘中的静态文件。

当完成了这一动态文件的存储以及操作之后,内核就会将数据同步到磁盘设备中。

内核会为进程设置一个专门的数据结构用来管理该进程,用来记录进程的状态信息、运行特征等。称之为PCB 进程控制块。

 

2.2 返回错误处理

当对文件操作出现错误的时候,难道没有错误返回提示吗?

不,实际上会有一个错误返回提示,系统已经写到了errno变量里面。不过不一定每一个函数都写有返回错误变量的操作, 需要用man手册来查看是否具有错误设置

用strerror函数以及perror函数可以查看错误提示。(查找百度看原型所需参数)

2.3 退出

在系统下,程序有两种退出方式: 正常退出以及异常退出。

正常退出: return  exit() _exit()  Exit();

_exit()函数原型

status: 参数内容 0表示正常结束,若为其他值则是检测到有错误。

 exit()函数 。其实一个标准的库函数 而上述的函数则是系统调用

用法是相通的。

2.4 空洞文件

空洞文件则是在超出文件大小的位置上进行偏移,则超出的区域则为文件空洞。那么文件也会成为空洞文件。

文件空洞实际上并不会占用任何物理空间,但是逻辑上是会包含了空洞部分的大小。

2.5讲解O_APPEND标志

该标志在open函数使用的时候添加,其功能是自动把文件当前位置偏移量移动到文件末尾。从文件末尾开始进行数据的写入。

2.6 多次打开同一个文件

1) 一个进程之内多次open打开同一个文件的时候,会得到多个不同的文件描述符fd,则在关闭的时候就需要一次的关闭这些文件描述符。

2)一个进程多次open打开同一个文件的时候,在内容中也不会存在多份动态文件。

从测试里面可以知道,尽管多次打开一个文件,则修改文件的时候也只修改一份,说明多次打开文件并不会生成多份动态文件。

3)多次open一个文件的时候,如果没有加标记,则是对同一个文件进行连续写的功能,为了实现写完一fd1后继续在后面写fd2则需要进行,增加标记O_APPEND 是文件偏移到末尾,就会完成连续写的内容。

实际上,O_APPEND标志涉及到原子操作的问题。所以能够完成连续写的请求。

 2.7 复制文件描述符

open返回的文件描述符,是可以进行复制的,复制后的文件描述符也可以对IO进行操作,并且与旧的文件操作符有相同的权限。它们的结构如下:

在使用过后也需要进行close进行关闭。

2.7.1 dup函数

复制文件描述符

 参数是需要复制的文件描述符。

系统返回一个新的文件描述符,具体由操作系统进行分配,遵循分配原则,失败则返回-1

经过测试,也可以发现,复制后的文件描述符,是保持连续写的功能。

2.7.2 dup2函数

新增参数: 返回一个新的文件描述符,该文件描述符可手动指定的值。

函数失败则返回一个-1

 2.8 文件共享

所谓文件共享是指同一个文件被多个独立的读写体同时进行IO操作。多个独立的读写体也可以理解为对应于同一个文件的多个不同描述符。

实现方式:

1) 同一个进程多次调用Open函数的打开一个文件,其数据结构如下:

最终指向同一个inode节点。说明共享了一个文件的内容。

2)不同进程分别使用open函数打开同一个文件,其数据结构如下:

 各自的文件表最终多索引到同一个inode节点,从而实现共享文件。

3)使用同一个进程通过对文件描述符进行复制来完成

(dup dup2)

2.9 原子操作以及竞争冒险

文件实现共享资源会有一个问题就是,出现竞争冒险。

操作共享资源的两个进程结果是不可预期的。每个进程的顺序是不可预期的,完全有操作系统调配。就会出现竞争状态。

 

解决这个问题,则需要进行原子操作。

原子操作则是多步操作组成一个操作,要么不执行,要么执行完所有步骤,不存在只执行步骤中的一个子集

1)O_APPEND 实现了原子操作。

使用这个标志的时候,open则会完成偏移文件到末尾,写入数据这两个步骤组成一个原子操作。

2)pread和pwrite函数

都是系统调用,并且可以传入一个参数,之后在进行文件的读写以及位置的偏移。

 3)创建一个文件 

open 函数中同时指定了 O_EXCL 和 O_CREAT 标志,如果要打开的文件已经存在,则 open 返回错误;如果指定的文件不存在,则创建这个文件。如果文件已经存在,则open返回错误,若文件不存在,则会创建文件,这是一种机制,保证了进程是打开文件的创建者。
主要完成了判断是否存在文件,创建文件,完成一个原子操作。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值