Linux文件(命令行文件操作、Linux文件操作、默认标准文件的底层原理)

Linux文件(命令行文件操作、Linux文件操作、默认标准文件的底层原理)

1. 命令行的文件操作

在c语言中,我们用 fwritefread 来读写文件,在写文件时,可以使用 w 来覆盖重写文件内容,也可以用 a 来追加文件内容。实际上读写文件是进程来执行的,文件的打开和关闭是CPU在执行我们的代码。所以在Linux中,也有一套读写文件的操作。

在命令行中 >命令与w含义相同,可以覆盖文件内容;而 >> 命令含义与 a 相同,可以在文件后面追加内容。

它们的使用方法如下:

2. Linux的文件操作

Linux中,使用 open() 函数来打开文件,这个函数有两种重载。其中两个参数的重载一般用来打开已经存在的文件 ;而三个函数的重载一般用来创建新的文件

头文件

c++ 复制代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags)

open()函数的 flags 参数是一个位图,以整型的形式传递。使用位运算符|可以以多种方式打开文件:

O_RDONLY: 以只读方式打开文件。

O_WRONLY: 以只写方式打开文件。

O_RDWR: 以读写方式打开文件。

O_CREAT: 如果文件不存在,则创建文件。

O_EXCL: 与O_CREAT一起使用,如果文件存在,则打开失败。

O_TRUNC: 如果文件存在且以写方式打开,则将其长度截断为0。

O_APPEND: 在每次写入时都追加到文件末尾。

O_NONBLOCK: 以非阻塞模式打开文件。


int open(const char *pathname, int flags, mode_t mode)

mode 参数为该文件的权限,以权限掩码的形式传参 。但要注意,系统已经存在默认的权限掩码,直接设置参数会影响文件最终的权限掩码。所以在设置文件的权限掩码时,还需要使用 umask() 函数来重置默认权限掩码,该函数不会影响系统的权限掩码,代码中的权限掩码因为就近原则使用重置的默认权限掩码。

mode_t umask(mode_t mask)

3. 理解文件操作

3.1 读写文件的底层原理

文件存储在硬盘中,所以向文件写入本质是向硬盘写入 。OS是文件的管理者,用户没有权限直接向文件写入,必须通过OS写入。所以文件写入必须使用系统调用,而我们使用的c和c++都是系统调用的封装。

因为文件储存在硬盘中,而OS在内存里,所以OS并不直接管理文件,而是使用类似于PCB的结构体来管理文件。

在Linux中,进程的task_struck里有一个指向files_struct结构体的指针,在这个结构体中存储了一个fd_array数组,这个数组记录着进程打开的文件的个数。

一个进程可以打开多个文件,文件描述符fd的本质是内核的进程,是文件映射关系的数组下标。其中,用户打开的文件下标从3开始,因为0、1、2分别存储着:

0 标准输入 键盘
1 标准输出 显示器
2 标准错误 显示器

在c语言的文件操作中也是如此,只是名字不同,分别对应为:

stdin 标准输入 键盘
stdout 标准输出 显示器
stderr 标准错误 显示器

被打开的文件用双向链表相互连接,而OS通过id记录的下标可以直接找到对应的文件。

文件描述符fd的分配规则:

查找自己的文件描述表,分配最小的没有被使用的fd。(实际上也可以把0、1、2文件关闭,这样新分配的fd也会去用这三个数字)。

对文件的读和写操作都不是直接对磁盘中的文件读写,而是有一个文件内核的缓冲区无论读写,都必须在合适的时候让OS把文件的内容读到文件缓冲区中。

所以我们在读写文件时,过程是:

读:OS通过fd找到对应的struct_file > 将硬盘中文件内容加载入文件内核的缓存 >将缓存内容拷贝到用户指定的区域

写:OS通过fd找到对应的struct_file >将写的内容拷贝入文件内核的缓存 > 将缓存的内容写入磁盘中的文件里

OS通过fd来查找文件,实际上OS只认fd,那么c和c++在使用读写文件的操作时,为什么没有使用fd也能操作文件呢?

在c语言中, FILE 实际上是库中提供的一种结构体,在这个结构体中实际也存储了文件的 fd ,因为 Linux 操作系统只认 fd ,C语言通过这个结构体让用户规避了直接接触 fd 描述符。在 c++ 中的 cincout 也是如此,本质上都会调用 fd 描述符。

C 和 C++ 设计自己进行文件操作接口的原因,是因为语言都要有跨平台性 。系统不同,系统调用的接口可能不一样,如 Linux 中使用文件描述符 fd 对文件进行管理和操作,但 Windows 中没有文件描述符的概念,所以直接使用系统调用的代码不具有跨平台性

但如果语言对不同平台的系统调用进行封装,将不同操作系统的系统调用封装成一样的接口。虽然底层使用的系统调用不同,但是顶层的语言接口使用方式相同,这样语言也就有了跨平台性。

3.2 默认标准文件的底层原理

Linux 中一切皆文件,所以fd的012下标中的键盘和显示器虽然是硬件,但在 Linux 中也是文件。同样的OS不直接管理硬件,而是通过管理结构体来间接管理硬件。

struct_file 结构体中有一个 device 结构体记录着文件的属性,还有两个函数指针分别指向驱动中实现读和写的函数,OS就是通过这种方式来以文件的形式来管理硬件。这种管理方式被称为 vfs (virtual file system)

相关推荐
HEX9CF5 分钟前
【Anaconda】Anaconda3 下载与安装教程(Ubuntu 22.04)
linux·运维·ubuntu
joker D8881 小时前
【CUDA】CUDA Hierarchy
linux·cuda·c/c++·并行计算
Tassel_YUE1 小时前
openEuler 22.03 使用cephadm安装部署ceph集群
运维·ceph·学习笔记·openeuler·技术分享·服务部署
APItesterCris1 小时前
对于大规模的淘宝API接口数据,有什么高效的处理方法?
linux·服务器·前端·数据库·windows
加洛斯2 小时前
SpringBoot小知识(3):热部署知识
运维·服务器·spring boot
苹果醋32 小时前
Springboot入门教程系列HelloWorld
java·运维·spring boot·mysql·nginx
济南小草根2 小时前
Nginx学习-安装以及基本的使用
运维·服务器·nginx
YRr YRr2 小时前
Ubuntu 20.04中的文件移动操作:详解与实用示例
linux·运维·ubuntu
北京迅为2 小时前
【北京迅为】iTOP-4412全能版使用手册-第三十二章 网络通信-TCP套字节
linux·嵌入式硬件·4412开发板
安静读书3 小时前
Docker使用教程
运维·docker·容器