Linux下的文件IO操作
1.前导
1.1文件知识
- 文件 = 文件内容 + 文件属性
- 访问文件的时候,都得先打开文件,修改文件都是通过代码去修改的,所以首先就得先把文件先加载到内存当中。
- 谁在打开文件?------ 进程在打开文件
- 一段时间内,OS当中肯定有很多进程,也肯定有很多被打开的文件,那么OS该怎么去取管理这些文件呢?----- 先描述,后组织
- 进程和文件的关系:struct task_struct 和 struct XXX
- 系统是不是把所有的文件都打开了?-------- 那一定是没有的,没有打开的文件都存储在磁盘当中。
1.2对比一下文件操作和重定向
1.2.1输入重定向
fopen以"w"方式打开:如果文件不存在,先会创建一个文件 / 如果文件存在,先会清空文件内容,然后再从头进行写入操作。
这上面的操作是不是和输入重定向很相似。
1.2.2追加重定向
fopen以"a"方式打开:本质也是写入,如果文件不存在,先会创建一个文件,然后进行写入 / 如果文件存在,会在文件原有内容的末尾处追加写入。
上面的操作是不是和追加重定向很像。
1.3当前路径
当文件不存在的时候,在当前路径下创建一个,那么进程又是如何知道当前文件的呢?--- 当然是记录在进程PCB当中的。
可以 ls /proc/pid 查看
补充函数:
int chdir(const char* path);
1.4stdin stdout stderr
三大标准输入,OS都默认帮你打开了。
一、标准输入流stdin
- 定义:标准输入是程序可以从中读取输入数据的位置,它默认指向键盘,但也可以被重定向为文件或者其他输入设备。
- 作用:允许用户通过键盘或者其他输入设备向用户提供数据,也可以从文件中读取数据。
- 文件描述符:在linux系统中,stdin文件描述符为0。
二、标准输出流stdout
- 定义:标准输出是程序用于发送其输出数据的位置,它默认指向终端屏幕,但也可以被重定向为文件或者其他输出设备。
- 作用:stdout用于显示程序的正常输出,包括结果、状态信息、其他非错误信息。
- 文件描述符:在linux系统中,stdout文件描述符为1。
- 缓冲:stdout通常是行缓冲的,意味着输出会先存储在缓冲区中,直到遇到换行符或者缓冲区满才会刷新到目的地。
三、标准错误输出流stderr
- 定义:标准错误是程序用于发送错误、异常信息的位置,它默认指向终端屏幕,但也可以被重定向为文件或者其他输出设备。
- 作用:用于输出错误信息,以便用户能够识别并解决问题。
- 文件描述符:在linux系统中,stderr文件描述符为2。
- 缓冲:stderr是非缓冲的,意味着错误信息会被立即发送到目的地,以便用户能够尽快的看到它。
2.文件操作的系统调用接口
访问文件不仅有C语言上的文件接口,OS必须提供对应的访问文件的系统调用接口。即:C标准库中的文件IO接口,底层一定封装了系统调用接口。
2.1.open()打开文件
- 功能:打开一个文件,如果文件不存在则创建文件。
- 返回值:打开成功,返回非负整数,即:文件描述符(用于后续文件操作);如果失败,返回-1,并设置errno以指示错误的原因。
- 底层调用Open,传递不同的参数,在上层表现为fopen以r、w、a方式打开文件。即:不同的fopen风格,代表着open传递了不同的选项。
2.1.2.flags参数
O_WRONLY O_CREAT O_APPEND
这三个大写的字符串,还是这种格式的,我们很容易就联想到宏。
- 参数flag:标记位,用于指定文件的打开模式(只读、只写、追加等)和其他选项(创建文件、截断文件等)。
- flag参数是一个整数,每个比特位代表一个标记位。通过位操作(|、&),可以一次性向函数传递多个标记位。
- 在编程中,涉及需要向函数传递多个布尔选项(标记位)时,使用单个整数(int,32位),并通过位操作来设置和检查这些选项,这种方法被称为"位图",是一种非常高效和节省资源的方法。
- 使用宏定义,来表示各种标记位,每个宏定义只有一位为1(每个宏中为1的位是错开的),其余位全为0。在这个整数中为1的位,用来表示某个特定的选项是否被设置。多个宏通过位操作(|按位或)组合,一次性地向函数传递多个标记位。即:通过位图的方式,传递多个标记位。
2.1.3.mode参数
文件不存在的时候,要创建文件时,要用mode参数设置权限,
如果没有设置权限就会出现下面的情况(权限乱码)
现在让我们来看看mode参数如何传参。
为什么我们用mode设置的文件权限是666,但是文件权限最终确实664呢?
(这是因为权限掩码的存在)
原因:默认(最终)权限计算公式 = 起始权限 & (~umask值) , 本质是从起始权限中去掉在umask权限中出现的权限,如果在起始权限中某权限位不存在,但umask中该权限位存在,该权限位的结果为0,"去掉"不是删除。
2.1.3 umask()函数
- 功能:设置文件的权限掩码。
umask函数只会影响调用它的进程所创建的权限掩码,而不会对父进程或其他进程的权限掩码产生影响。
2.2.write()向文件写入
- 功能:向打开的文件中写入数据。
- 参数:fd,表示写入数据的文件或设备; buf,指向要写入数据的缓冲区的指针; count,要写入的字节数。
- 如果buf为const char*类型,strlen(buff),不需要在后面+1,即:不需要把字符串结束标志\0写入进去。因为c语言字符串以\0结尾,\0不是字符串内容,而是作为字符串结束标记,与文件无关,若把\0写入,则会造成乱码。
- 返回值:如果成功,返回实际写入的字节数。如果出错,则返回-1,并设置errno以指示错误。
2.3.read()从文件读取
-
功能:从打开的文件中读取数据。
-
参数:fd,表示要读取数据的文件或设备; buf,指向读取数据的缓冲区的指针; count,要读取的最大字节数。
-
返回值:如果成功,返回实际读取的字节数。如果出错,则返回-1,并设置errno以指示错误。如果到达文件末尾(EOF),则返回0
2.4.close()
-
功能:关闭一个打开的文件描述符。
-
返回值:如果成功,返回0。如果失败,返回-1,并设置errno以指示错误。
- 点赞
- 收藏
- 关注作者
评论(0)