网站运营费用,seo推广优化公司,徐州教育学会网站建设,外链网站 风险标题#xff1a;[Linux] 文件系统 #xff08;1#xff09;—— 进程操作文件 个人主页水墨不写bug #xff08;图片来源于网络#xff09; 目录 一、进程与打开的文件 二、文件的系统调用与库函数的关系
1.系统调用open()
三、内存中的文件描述符表
四、缓冲区… 标题[Linux] 文件系统 1—— 进程操作文件 个人主页水墨不写bug 图片来源于网络 目录 一、进程与打开的文件 二、文件的系统调用与库函数的关系
1.系统调用open()
三、内存中的文件描述符表
四、缓冲区的理解
五、俯瞰IO 正文开始 一、进程与打开的文件 C/C都提供了对文件进行操作的函数接口想要对文件操作无论是往文件中写入还是从文件中读出都需要满足一个前提条件文件被打开。 文件被打开意味着文件被从磁盘中加载到内存中。进程是我们写的C/C指令编译行成的运行起来的程序本质是我们想要完成想要某一个任务。于是我们不得不考虑加载到内存中的文件与进程之间的关系。 文件是在磁盘中存储的磁盘是一个硬件外设对文件操作本质就是对磁盘这个硬件操作。但是用户没有权利直接向硬件写入。想要完成对硬件操作需要 软硬件资源的管理者——操作系统的帮助。但是操作系统不相信如何用户于是需要用操作系统提供的安全的访问操作系统数据的方式——系统调用。 于是我们通过分析可以推测——我们使用的 fopen/fwrite/fread/fprintf/scanf/printf/cin/cout 等一系列的C/C的文件操作的库函数本质都是对系统调用的封装 这样一来为了搞清楚封装的细节我们需要先知道如何使用系统调用。 二、文件的系统调用与库函数的关系
1.系统调用open() open()函数原型 参数 pathname想要打开的文件的名称; flags打开的文件的方式选项常见的选项有 O_WRONLY: 以写的方式打开文件。 O_CREAT: 如果不存在就创建文件。 O_TRUNC: 每一次打开清空文件内容。 O_APPEND:打开文件之后不清空文件内容而在后面追加。 mode如果成功创建了文件文件被创建出来的默认权限设置。 返回值 一个整数int被称为文件描述符file descriptor。 其实C语言的fopen函数在的不同打开方式都对应一种flags的组合。C语言对文件打开方式有w r等等的区分由于C语言fopen函数底层调用的还是open系统调用所以自然会发现这样的对应关系 这两个调用本质都是对第一个系统调用函数open的调用只不过第二种C语言式的函数调用对第一种系统调用进行了封装在函数内部增加了语言级别的缓冲区等的操作并且对返回值也进行了封装把int类型的返回值封装成了FILE结构体指针类型的返回值。 为什么C语言要这样做呢别急接下来我们对文件有了深入的理解认识之后你就会体会到C语言的良苦用心了。 三、内存中的文件描述符表 在上面的理解中我们发现 系统调用open()函数 的返回值是一个整形int对应的我们发现 系统调用close() 函数也是通过一个int整数来关闭文件的这非常令人费解为什么仅仅凭借一个整数就可以操作整个文件的开关 在操作系统中运行有成百上千的进程每时每刻都有进程的创建消亡。每一个进程都可以打开文件并且一个进程可以打开不止一个文件这就意味着操作系统必须要有一个高效的管理打卡的文件的方式这个方式就是 先描述再组织 在内存中不止有进程的PCBtask_struct还有描述文件的数据结构文件描述符表 我们可以暂时把文件描述符表抽象理解成一个数组这个数组存储文件的数据。磁盘中的文件被加载到内存中就是通过这个数组来维护的。 而open的返回值就是打开的文件在这个数组中对应的下标 如上图一个个的文件被加载到内存中后会被存储在files_struct这个结构体数组中这个数组就是文件描述符表 不同的文件存储在不同下标位置 于是每一个文件就有了一个对应的下标fd这也就解释了为什么操作系统为什么可以拿着一个整数来对文件进行操作因为操作系统可以通过一个整数下标来标识一个文件。 当我们一次性打开并关闭多个文件重复几次会发现fd的分配规则 1fd的0,1,2被默认提前分配为标准输入键盘标准输出显示器标准错误显示器。C语言的stdinstdoutstderr本质也是对这三个文件的封装 2fd的分配机制是按照从小到大的顺序分配fd下标。 四、缓冲区的理解 语言有语言的缓冲区系统有系统的缓冲区这两个缓冲区存在的目的都是为了提高IO效率 1因为访问外设与CPU的速度相比非常慢所以系统缓冲区存在的意义就是尽量减少对外设的访问当向缓冲区写入一定量的数据之后操作系统会一次性把数据刷新到磁盘中。 2系统调用的使用成本比库函数要高的多因为操作系统太忙了每一次调用系统调用都是请求操作系统配合用户一次频繁调用会导致效率损失。所以语言缓从区存在的意义就是尽量少调用系统调用当我们向语言级缓冲区写入一定的数据之后C语言函数会一次性把数据刷新到系统级缓冲区。 五、俯瞰IO 这时我们整体俯瞰io的过程 当我们打开一个文件操作系统会调用open 1创建file结构体 2开辟文件缓冲区内容加载问价数据延后 3查进程的文件描述符表 4file地址填入对应的表的下标中 5返回下标 当我们调用fopen库函数会在上面操作的基础上创建语言级缓冲区等操作本质是为了改善用户体验提高效率。 为什么C语言要封装系统调用 1提高效率改善用户体验 2C语言有多个不同的在不同的平台上实现的版本具有跨平台性。但是我们所讲的系统调用仅仅是Linux的对于其他操作系统就不适用了。 完·~ 未经作者同意禁止转载