Linux知识点 – 基础IO(一)
文章目录
一、预备知识
1.Linux下一切皆文件
C/C++程序会默认打开三个文件流:
可以看出,这三个流都是文件;
键盘,显示器等也都可以被看作文件;
2.对文件的操作
文件在磁盘上存放着,当我们写代码访问文件时,实质上是进程在访问文件;
我们要向硬件进行写入,只有操作系统有权限,如果普通用户也想写入,就必须由操作系统提供接口:
- 系统调用接口:比较难,但是操作系统层面的文件接口只有这一套,每种语言的文件操作都是对这套接口的封装;
- 语言级别的文件接口:不同语言的文件接口不同,可以帮助用户实现跨平台运行;如果只是用系统接口,换个系统平台,这套代码就将无法运行了;
3.理解文件
站在系统的角度:能够被input读取,或者能够呗output写出的设备就叫做文件;
- 狭义上的文件:普通的磁盘文件;
- 广义上的文件:显示器,键盘,网卡,显卡,磁盘。几乎所有外设都可以称之为文件;
二、C语言文件读写接口
1.当前路径
当一个进程运行起来的时候,每个进程都会记录自己当前所处的工作路径,这就叫做当前路径;
c语言的文件接口,如果只给文件名而并没有指定路径,该文件的路径就会默认为当前路径;
2.写入
w方式写入文件,再写入前就将文件内容先清空了;
注意:
- fwrite的第二个参数strlen不需要加1,因为字符串后面加一个\0是C语言的规定,文件是不需要遵守的,文件只用保存有效信息;
- 重定向是会事先将文件中的内容清空后,再写入的:
直接使用 >log.txt 可以清空log.txt中的所有内容:
3.追加
a方式写入文件,向文件末尾追加内容;
4.读取
fgets按行读取:
使用命令行参数获取文件名:
从命令行参数获取文件名然后打印,相当于cat命令:
三、系统文件IO接口
1.open
参数:
- pathname:文件的路径+文件名;
- falgs:宏标志位,每一个宏都对应一个位,代表一种状态,使用位图来实现的,可以同时传入多个状态;
与下面的代码中的flags是一种标志位:
多个标志位共同存在,中间用 | 隔开; - mode:用来设文件置权限的参数,使用八进制权限;
- 返回值:fd(file descriptor)文件描述符;
标志位O_WRONLY代表只写,O_CREAT代表文件不存在时创建文件;
运行结果:
返回的是文件描述符;
当我们查看文件权限时:
该文件的权限是不对的,是因为我们没有设置权限,使用open的重载函数能够在mode参数中设置权限:
将umask权限掩码设为0;
2.close
关闭文件;
只需传入文件描述符,就可以关闭打开的文件;
3.write
参数:
- fd:文件描述符;
- buf:需要写入的字符串;
- count:字符串的长度;
- 返回值:成功,返回实际写入的长度;失败,返回-1;
运行结果:
- 在open中加上O_TRUNC标志位,代表打开之前清空文件;
运行结果:
- 在open中加上O_APPEND标志位,代表追加写入文件;
运行结果:
4.read
标志位O_RDONLY表示只读;
运行结果:
四、文件描述符
1.验证
- 连续创建文件,打印文件描述符:
运行结果:
可以看到,这几个文件的文件描述符fd是从3开始依次排列的; - 如果用read读取,文件描述符fd传0:
其实stdin、stdout、stderr的文件描述符分别为0, 1, 2;
2.文件描述符
-
文件描述符是从0开始的小整数;当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述文件,就是所谓的先描述,后组织,于是就有了file结构体,表示一个已经打开的文件对象;
-
创建struct file的对象,充当一个被打开的文件,再用双链表组织起来;
-
每个进程都有一个*files指针,指向一张表 file_struct,该表最重要的部分就是一个包含一个指针数组,每个元素都是一个指向打开文件的指针;
-
struct file的对象中一定封装了文件描述符fd;
-
fd在内核中,本质是一个数组下标,一个进程中可能打开多个文件,使用fd来标识这些文件;
-
所以,只要拿着文件描述符,就可以找到相对应的文件;
-
Linux中文件读写的过程:
程序调用fwrite函数 -> 传入FILE参数 -> FILE中有该文件的fd -> 调用系统接口read/write -> 传入该文件的fd -> 自己执行操作系统内部的write方法 -> 能找到进程的task_struct -> *files -> files_struct -> fd_array[fd] -> struct file -> 内存文件被找到了 -> 操作;
3.文件描述符的分配规则
从上面可以看出,文件描述符正常是从3开始分配的,是因为stdin,stdout,stderr的文件描述符以此为0, 1, 2;
- 如果把0号文件关掉:
由上图的结果可以看出,如果将0号文件关闭,再打开自己的文件,则该文件在这个进程中的fd为0;
由此可得,fd的分配规则为:最小的、且没有被占用的文件描述符;