【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件

目录

​编辑

前言

系统调用

open

参数flags

 参数mode

write

追加方式

read

close

 文件描述符

打开多个文件并观察其文件描述符

C语言文件操作

理解一切皆文件 

理解open操作


前言

各类语言的文件操作其实是对系统调用的封装

我们经常说,创建一个文件,或者打开一个文件,其实并不是我们用户本身创建,而是进程创建文件。文件是存储在磁盘上的,是硬件,像文件写入其实就是向硬件写入,而我们用户这一角色是没有权力直接写入的,操作系统(OS)是硬件的管理者,必须要通过OS写入;

但是,OS不相信任何人,只是提供了系统调用接口对外,想访问文件,就需要使用系统调用;而C/C++..语言都提供了这些系统调用的封装,为何要封装呢?跨平台性。

系统调用

open

打开一个文件,返回一个文件描述符,可以以flags形式打开文件

//2号手册 是系统调用(System Calls)  查找系统调用里面的open函数
man 2 open   

pathname:表示文件的路径名,也可以是一个文件名;如果没有路径名,默认在当前文件下;
flags:表示打开文件的方式选项,参见选项有: 

  • O_WRONLY:只写打开
  • O_CREAT:文件不存在时创建文件
  • O_RDONLY:只读打开
  • O_RDWR:读写方打开
  • O_APPEND:追加方式打开
  • O_TRUNC:清空文件,重新写入

mode:如果这个文件不存在,那么以写的方式打开的时候就会创建这个文件,在创建文件的时候需要给这个文件设定权限(使用八进制数)(会被umask影响);

        如果这个文件存在的话,那么就不用传第三个参数了,因为文件的权限已经确定了

参数flags

open函数定义中,flags是以整形定义的,有32比特位,满足参数个数不固定的情况,以二进制形式传参;

        实际上是一个32位二进制的位图,位图(Bitmap)是一种基于位操作的数据结构,用于表示一组元素的集合信息。位图中的每个二进制位都表示着某个元素是否在集合中。

        比如宏O_WRONLY假设表示的是2即10(二进制),O_CREAT表示4,即100(二进制)。那么O_WDONLY|O_CREAT=110(二进制)。在open函数内部就会有相应的机制监测flags的二进制位哪些是1,再分别对应其代表的功能

 参数mode

表示一个四位八进制的数,取后三位来表示各个角色的权限;

例:0666,取666用二进制表示的就是110 110 110分别对应文件的拥有者、所属组、其他人的(other)权限。

如果当文件不存在时,就要设置该参数,不然就会出现权限处乱码

当新建一个文件时,一定要加上mode参数,来设置权限

 

umask默认为002,也就是过滤掉了“其他人”的w权限,所以得到的最终文件权限编码是664。 

文件权限和权限掩码的关系:文件权限& (~umask权限掩码)

write

用于向文件中写入数据。通过指定文件描述符、数据来源的缓冲区地址和要写入的字节数;可以将数据写入到文件中。如果写入失败则返回-1,否则返回写入的字节数;

  • fd表示的是文件标识符
  • buf表示的是数据的地址;
    • 对于系统调用来说,它并不在意写入的数据是什么类型的,它接收到的数据都是二进制的数字,然后按照字节为单位写入。
  • count表示的是字节数
  • 返回值类型: ssize_t 类型表示有符号整型,输出格式为%ud.

 

追加方式

以追加方式写入,只需要在open(...)第二个参数中 把O_TRUNC换成O_APPEND

read

用于从文件中读取数据。通过指定文件描述符、缓冲区地址和读取的字节数;

可以将文件中的数据读取到缓冲区中。

读取成功返回读取的字节数,否则返回-1.

int fd:打开文件时返回的文件描述符。
void* buf:从文件中读取的数据放在这个数组中,同样系统不管文件中的数据类型是什么,都是按字节放入这个数组中。
size_t count:要读取的字节个数。
ssize_t:读取了多少个返回多少。 

使用只读方式打开(目标文件已经存在,open(...)中mode参数可以不用加入设置);

将读取的内容放在ch_arr数组中。 

close

用于关闭一个文件描述符,释放系统资源。(也就是令struct file* fd_array[]对应下标fd指向空。)

在文件操作完成后,应该及时关闭文件描述符,以防资源泄漏。

关闭成功返回0,否则返回-1.

 文件描述符

 操作系统要管理文件,必定要让文件先加载到内存,然后先描述,再组织。内核中要有描述对应文件的结构体——也就是struct file

        struct file中最核心的数据可以分为3大类,属性,方法集,缓冲区。而文件描述符fd就存在属性当中。

        文件是由进程发起创建的,而一个进程实际上是一个PCB(task_struct),里面有一个结构体指针struct file_struct* files,指向了一个结构体。这个结构体中又有一个指针数组struct file* fd_array[N]该指针数组存放了指向进程所打开文件的结构体下标,也就是文件描述符fd;

  • 内核会返回一个小的非负整数。这个非负整数就叫做描述符,也叫文件描述符。文件描述符是用于唯一标识文件的号码。
  • 进程实际上并不记录文件本身,而只需要记录一个为一个文件ID。所有被打开的文件的信息都被集中在一起被内核管理,内核向进程提供文件的接口。

打开多个文件并观察其文件描述符

创建的每一个进程开始的时候都有三个打开的文件:标准输入流(fd=0),标准输出流(fd=1),标准错误流(fd=2)。

 这三个文件分别对应的硬件设备是键盘、显示器、显示器。

而这三个都是默认自动打开的

 

当进程打开文件时,会在struct file*数组中找到当前没有被使用的最小的下标,作为新的文件标识符。

如果在打开文件之前,把这个三个文件流关闭,那么就会自动分配到当前的最小下标。

C语言文件操作

C语言文件操作默认打开三个输入输出流,分别是stdin,stdout,stderr。 

 之前提到过,不同语言的文件操作不过是对系统调用的封装,这里发现C语言的返回值和系统调用open..返回值不一样,我们大胆猜测FILE是一种封装

 打印输入输出流

 

 可以发现,FILE结构体中是有文件描述符的。

文件描述符fd的分别规则是:从小到大,按顺序查找,将没有被占用的数组下标作为被打开文件的文件描述符fd值。

理解一切皆文件 

这个文件可以理解成结构体

  • 每一个硬件,操作系统都会维护一个struct file类型的结构体,硬件的各种信息都在这个结构体中,并且还有对应读写函数指针(对硬件的操作主要就是读写)。
  • 每个硬件的具体读写函数的实现方式都在驱动层中,使用到相应的硬件时,操作系统会通过维护的结构体中的函数指针调用相应的读写函数。

 

  •  站在操作系统的角度来看下层,无论驱动层和硬件层中有什么,在它看来都是struct file结构体,都是通过维护这个结构体来控制各种硬件。
  • 站在操作系统的角度来看上层,无论用户层以及系统调用有什么,在它看来都是一个个进程,都是一个个的task_struct结构体,都是通过维护这个结构体来调度各个进程的。
  • 真正的文件在操作系统中的体现也是结构体,操作系统维护的同样是被打开文件的结构体而不是文件本身。

理解open操作

  • 创建struct file(包括fd)
  • 开辟文件缓存区,加载文件中的数据(延后)
  • 查进程的文件描述符表(fd_array数组)
  • 将file的内存地址填入到fd_array[fd]中
  • 返回fd. 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1487048.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】:自定义shell(简易版)

朋友们、伙计们,我们又见面了,本期来给大家带来一期自定义shell,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数据结构专栏…

虚拟现实和增强现实技术系列—Expressive Talking Avatars

文章目录 1. 概述2. 背景介绍3. 数据集3.1 设计标准3.2 数据采集 4. 方法4.1 概述4.2 架构4.3 目标函数 5. 实验评测5.1 用户研究5.2 我们方法的结果5.3 比较与消融研究 1. 概述 支持远程协作者之间的交互和沟通。然而,明确的表达是出了名的难以创建,主…

SSRF中伪协议学习

SSRF常用的伪协议 file:// 从文件系统中获取文件内容,如file:///etc/passwd dict:// 字典服务协议,访问字典资源,如 dict:///ip:6739/info: ftp:// 可用于网络端口扫描 sftp:// SSH文件传输协议或安全文件传输协议 ldap://轻量级目录访问协议 tftp:// 简单文件传输协议 gopher…

媒体邀约专访与群访的区别?

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体邀约中的专访与群访在多个方面存在显著差异,以下是对这两种采访方式的详细比较: 一、定义与形式 专访: 定义:专访是指由媒体记者对单…

iOS 开发包管理之CocoaPods

CocoaPods(Objective-C 时期,支持Objective-C和swift),CocoaPods下载第三方库源代码后会将其编译成静态库.a 文件 或动态库框架.framework 文件 的形式,并将它们添加到项目中,建立依赖关系,这种…

CPU与IO设备交互

距离cpu比较近的总线速度快,价格昂贵一些,根据重要程度选择总线,cpu不是通过总线直接和io设备相连接的,而是通过设备控制器进行连接的,暂时只需要关注cpu和设备控制器的直接进行的操作。 通过判断状态寄存器是否usy或者…

数据融合工具(15)线层、面层打折自动检测修复

一、内容导读 一个工具解决包括极小角在内的线层、面层要素的打折数据质量问题…… 小编提供了很多功能强大,应用场景广发的数据融合辅助工具集,能高效解决数据融合需要…… 数据融合工具(1)指定路径下同名图层合并 数据融合工具…

Linux云计算 |【第一阶段】SERVICES-DAY6

主要内容: Linux容器基础、Linux容器管理、podman命令行、管理容器进阶 实操前骤:安装 RHEL8.2 虚拟机 1.选择软件包:rhel-8.2-x86-dvd.iso; 2.内存2048M; 3.时区选择亚洲-上海,带GUI的服务器&#xff1b…

后端接口返回图片,前端的处理方法

接口返回如下图所示: 打印结果如下图所示: 出现问题的原因的axios默认返回的是json文本形式,二进制图片数据被强制转换成了 json 文本形式 处理方法: 首先,在axios中,将responseType默认返回数据类型json…

Python轻量级邮件发送库库之salmon使用详解

概要 电子邮件是现代通信的基础,在许多应用程序中,自动发送电子邮件是一个常见需求。salmon-mail 是一个基于 Python 的轻量级邮件发送库,它提供了简洁且强大的 API,用于处理电子邮件的发送和管理。本文将详细介绍 salmon-mail 库,包括其安装方法、主要特性、基本和高级功…

React 学习——行内样式、外部样式、动态样式

三种样式的写法 import "./index.css"; //同级目录下的样式文件 function App() {const styleCol {color: green,fontSize: 40px}// 动态样式const isBlock false;return (<div className"App">{/* 行内样式 */}<span style{{color:red,fontSiz…

科技引领水资源管理新篇章:深入剖析智慧水利解决方案,展现其在提升水资源利用效率、优化水环境管理方面的创新实践

本文关键词&#xff1a;智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…

破解网络奥秘:一图胜千言,TCP重传、滑动窗口、流量与拥塞控制全解析

引言 TCP 是一个非常复杂且伟大的协议&#xff0c;它通过许多机制来确保传输的可靠性。为了实现这一目标&#xff0c;TCP需要处理各种问题&#xff0c;比如数据损坏、丢包、重复数据以及分片顺序混乱等。如果这些问题得不到解决&#xff0c;可靠传输就无从谈起。 众所周知&am…

C++系列-list的模拟实现

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 构造函数生成 template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;ListNode(const T& data T()):_next(nullptr),_prev…

在 Android 上实现语音命令识别:详细指南

在 Android 上实现语音命令识别:详细指南 语音命令识别在现代 Android 应用中变得越来越普遍。它允许用户通过自然语言与设备进行交互,从而提升用户体验。本文将详细介绍如何在 Android 上实现语音命令识别,包括基本实现、带有占位槽位的命令处理,以及相关的配置和调试步骤…

Linux嵌入式学习——数据结构——概念和Seqlist

数据结构 相互之间存在一种或多种特定关系的数据元素的集合。 逻辑结构 集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等。 线性&#xff0c;数据和数据之间是一对一的关系。数组就是线性表的一种。 树&#xff0c; 一对多 图&#xff0c;多对多 …

压测实操--kafka broker压测方案

作者&#xff1a;九月 环境信息&#xff1a; 操作系统centos7.9&#xff0c;kafka版本为hdp集群中的2.0版本。 kafka broker参数 num.replica.fetchers&#xff1a;副本抓取的相应参数&#xff0c;如果发生ISR频繁进出的情况或follower无法追上leader的情况则适当增加该值&…

Java---String类

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 前言 在C语言中已经涉及到字符串了…

[前端]解决Iframe即使设置高度100%,但还是显示滚动条scrollbar的问题

前言 好烦,你看看这两个重复的滚动条. 一个是来自iframe,另一个来自父级的div(overflow: auto;) 我已经在css中设置了iframe的height: 100%;border: none;,但无论如何还是显示出了父级的scrollbar 解决 将iframe的display: block;即可. 或者vertical-align: bottom;

【启明智显分享】基于国产Model3芯片的7寸触摸屏助力智慧医疗,电子床头屏提升护理交互

未来医院必然是以信息化为基础&#xff0c;以物联网为特征&#xff0c;以医疗为核心的服务型医院。病房作为医院的重要服务场所&#xff0c;成为智慧医院建设的重要一环。 为提高医护人员与患者的互动交流&#xff0c;给医疗注入智慧元素&#xff0c;让患者享受智能服务&#…