Linux之基础IO

news2024/12/26 15:34:23

文章目录

    • 一.关于文件的共识
    • 二.复习C语言的文件操作
      • 1.打开文件
      • 2.向文件中写入数据
      • 3.向文件中追加数据
    • 三.有关文件的系统调用
      • 1.open(文件打开)
      • 2.write(向文件写入)
      • 3.read(读文件)
    • 四.文件描述符
      • 1.进程如何找到自己的文件
      • 2.为什么文件的fd都是从3开始的
      • 3.FILE和fd的关系
      • 4.文件描述符的分配规则
    • 五.重定向
      • 1.如何改变标准输入/输出
      • 2.输出和追加重定向
        • a.输出重定向
        • b.追加重定向
      • 3.输入重定向
      • 4.子进程重定向会影响父进程吗
    • 六.Linux如何做到一切皆文件

一.关于文件的共识

1.即使是空文件也要在磁盘中占用空间,因为文件=文件数据+文件属性,空文件没有文件数据但是仍然有文件属性。

2.因为文件=文件内容+文件属性,所以对文件的操作无非就是对内容/属性的操作。

3.在一个C程序中调用了文件操作函数,如果程序没有被执行这些文件操作函数也不会执行;只有这个程序被执行了这些文件操作函数才会被调用;因此文件操作的本质就是进程和被打开文件之间的关系

4.文件的唯一标识是“文件路径+文件名”,如果不指明路径默认是当前路径。

什么是当前路径?

在这里插入图片描述

当一个程序被执行时,其有关属性中有两个最显眼,一个是exe:表示当前执行的是哪个路径下的哪个程序;另一个是cwd:表示当前执行程序的工作目录

进程的工作目录就是这个进程的当前路径


Linux支持更改进程的当前路径,通过调用系统调用chdir(要更改的路径名)即可

在这里插入图片描述

在这里插入图片描述


二.复习C语言的文件操作

1.打开文件

在这里插入图片描述

fopen打开文件:

1.”w“以写方式打开,如果不存在就创建,默认是覆盖式写(清空文件原内容,写入新内容);

2.”r“以读方式打开,如果文件不存在就出错

3.”r+“读写方式打开,不存在出错

4.”w+“读写方式打开,不存在就创建

5.”a“追加打开,在文件原内容后面添加新内容


2.向文件中写入数据

在这里插入图片描述

按照%s%d的格式将后面的参数写入到f所指向的文件中

3.向文件中追加数据

在这里插入图片描述

只要改变打开方式即可


三.有关文件的系统调用

每种语言都有自己的文件操作函数,但是要想访问文件是无法绕过操作系统的,无论是文件的打开关闭还是读写都要经由操作系统之手,而我们要向操作系统发送请求就必须要调用系统调用。

也就是说无论何种语言的文件操作函数都是对文件方面的系统调用的再封装,但是它们各自的封装都是不同的。直接学习系统调用就能有效减少学习成本,因为上层语言是变化的,但是底层的系统调用不变,并且上层语言依赖于下层系统调用


1.open(文件打开)

标记位flags使用六个宏进行传参,他们分别是O_RDONLY(只读), O_WRONLY(只写),O_CREATE(创建), 和O_RDWR(读写),O_TRUNC(覆盖式写),O_APPEND(追加式写)

标记位利用了每个比特位只有01两种数字的特点,通过不同比特位中不同位置的1来表示不同的标记,所以对于flags中的五个宏的比特位序列一定是不同的

如果调用成功就返回打开文件的文件描述符,失败就返回-1

与open对应的系统调用接口是close,在打开文件以后最好手动调用close关闭文件


在这里插入图片描述

在我们使用C语言的文件操作函数时,以写方式打开文件如果文件不存在就会自动创建;但是系统调用这里即使是写方式打开不存在的文件也会出错,因为C语言的文件操作函数在调用系统调用是flags传的参数是O_WRONLY|O_CREATE

在这里插入图片描述

文件在创建时默认权限是666,目录是777,但是还要受到系统umask码值的影响,最终的权限是:默认权限&~umsak

当我们开始使用系统调用时发现相比语言来说操作并不是那么简单随意,因为此时语言所做的事就由我们自己来做了(我们长大了哦)

C语言创建文件默认的权限是正确的是因为它在使用open函数时还使用了第三个参数:

在这里插入图片描述

如果文件已经存在就没必要在打开文件时还传入第三个权限参数

如果不想受系统umask的影响,可以使用系统调用umask来更改

在这里插入图片描述


2.write(向文件写入)

在这里插入图片描述
在这里插入图片描述

这个输出结果好像不太对劲,虽然将wb和cnt正确输出了,但是为什么最后还有一个wbm1呢?

write是覆盖式写,并不会自动将文件清空,除非在open的时候加入O_TRUNC

在这里插入图片描述

如果不想直接覆盖式写,可以将O_TRUNC改成O_APPEND

在这里插入图片描述


3.read(读文件)

在这里插入图片描述
在这里插入图片描述

将fd代表的文件中的数据读取到buf所代表的缓冲区中


四.文件描述符

一个系统中一定存在着大量的被打开的文件,这些文件要被管理起来,因此操作系统对文件先描述后组织形成了struct file{}结构体,这个结构体包含了文件的大部分属性。

不但文件要被管理起来,每个文件的内核数据结构(struct file)也要被管理起来,所有就有了文件描述表(struct file_struct)。此时至少有一个这样的认识:
在这里插入图片描述


1.进程如何找到自己的文件

一个进程可能打开不止一个文件,同时内存中又存在大量被打开的文件,那么进程如何知道哪些文件是属于自己的呢?答案是通过文件描述符表,文件描述符表是一个数组指针,它的每一个元素都是一个指针,指向一个文件的内核数据结构,每个进程的PCB中都有一个指针指向文件描述符表

现在将结构补全:

在这里插入图片描述

每个进程的PCB中都存放了一个文件描述符表指针,通过这个指针就可以找到文件描述符表,该进程文件描述符表中元素所指向的文件都是该进程的文件

2.为什么文件的fd都是从3开始的

在这里插入图片描述

通过上面的结构我们就很清楚的知道为什么当我打开一个文件时这个返回值是3,这个返回值其实是文件描述符的下标;

系统会默认打开标准输入流,标准输出流和标准错误,它们分别占了文件描述符的0,1,2下标,所以新打开的文件只能占用3下标了。

在这里插入图片描述

3.FILE和fd的关系

想要访问文件绕不开操作系统,想让操作系统帮你找到某一个文件,你必须要有这个文件的文件描述符。因此,FILE这个结构体中必定要有文件描述符fd。

4.文件描述符的分配规则

系统调用close是用来关闭文件的,那么我可以关闭默认打开的三个标准文件吗?

在这里插入图片描述

0下标的文件被关闭以后,新打开的文件下标就是0。这是因为文件描述符的分配规则是自上到下扫描找到最小且没有被占用的下标分配给新打开的文件

在这里插入图片描述

当我将1关闭以后,再执行myfile,并没有输出任何东西,这点足以证明即使是三个默认被打开的文件也是可以通过close关闭的。

当我把1关闭以后,我新打开的文件就变成了那下标为1的文件,也就是说标准输出从显示器变成了我刚打开的文件,内容应该是输入到文件中了,我们打开文件看看:

在这里插入图片描述

为什么什么也没有?

因为这里还涉及到一个缓冲区的问题,向显示器中刷新数据和文件中刷新的策略是不一样的

在这里插入图片描述

我将本来应该打印到显示器上的内容打印到了文件中,这正好输出重定向


五.重定向

将本该打印到显示器的内容打印到某个指定的文件中就是输出重定向,所以说重定向的本质就是上层用的fd不变,在内核中更改fd对应struct file*的指向

1.如何改变标准输入/输出

改变标准输入/输出的本质是改变文件描述符表中0,1下标的内容

在文件描述符分配规则中先关闭标准输入/输出,在打开一个新文件,此时这个新文件就会占用刚刚关闭的标准输入/输出流的位置,这是一种改变方法,但这样写有些太挫。

操作系统提供了dup2的系统调用,用于改变标准输入/输出:

在这里插入图片描述

dup2就是将oldfd中的内容,拷贝到newfd中

通过dup2系统调用就能很轻松的实现重定向的功能。

2.输出和追加重定向

a.输出重定向

因此之间的输出重定向可以写成这样:

在这里插入图片描述

结果变成了3,这是因为dup2是一种拷贝,最后newfd和oldfd都变成了oldfd的内容,也就是说新打开的文件仍然是被文件描述符表中的3下标中的指针指向,但是代表标准输出的0下标中的struct file*也指向了新打开的文件。

b.追加重定向

在这里插入图片描述

追加重定向也是输出重定向的一种,原本追加的内容是直接打印到显示器上,现在也放到了文件中


3.输入重定向

在这里插入图片描述

所谓输入重定向就是将文件中的内容读取出来并打印到显示器上

4.子进程重定向会影响父进程吗

子进程的重定向不会影响父进程,子进程在创建时是以父进程为模型的,它会拷贝父进程的部分内核数据结构其中就包括了文件描述符表,子进程中文件描述符表的struct file*的指向变了,关我父进程什么事。

进程具有独立性,所有它们的文件描述符表也是各自持有一份。

六.Linux如何做到一切皆文件

一切皆文件的难点在于如何将硬件也作为文件来看待:

在这里插入图片描述

操作系统对每一个文件先描述后组织形成了struct file内核数据结构,在这个内核数据结构中存放了文件的大部分属性,其中还包含着一大批函数指针,这些函数指针指向的是某个文件的具体读写方法。

虽然每个文件都是不一样的,但是文件的属性有很大的相似性,为了方便管理可以将文件抽象成文件属性,对文件的描述就是对文件的属性描述,因为管理的本质是对数据进行管理。

将硬件用同样的方式来管理,将硬件的读写方法抽象成函数指针,各种属性抽象到struct file内核数据结构中。

当我站在struct file之上来看,所有的东西包括硬件都是统一由struct file来管理的,所以对我来说硬件也就和文件一样了。因此就造成了一种一切皆文件的现象。

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

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

相关文章

leetcode刷题(3)

各位朋友们大家好,今天是我leedcode刷题系列的第三篇,废话不多说,直接进入主题。 文章目录分割链表题目要求用例输入提示做题思路c语言代码实现Java代码实现相交链表题目要求用例输入提示做题思路c语言实现代码Java代码实现分割链表 leetcod…

KDSL-82轻型升流器

一、产品概述 KDSL-82 1000A大电流发生器是一种作为检验用的电流源,大电流试验器采用ARM芯片控制输出工艺和大容量的环形变压器,并且配有液晶屏显示的表计,同时显示一、二次电流、变比和秒表接点(或电位)的动作时间。外配铝合金机箱&#xff…

OceanMind海睿思受邀参加中小企业数字化转型发展论坛

近日,由江苏省企业信息化协会主办的中小企业数字化转型发展论坛于南京圆满结束。论坛重点邀请了南京市中小企业制造标杆、专精特新“小巨人”企业等相关信息化负责人和IT工作者共同探讨中小企业数字化转型的发展路径。 OceanMind海睿思作为南京地区大数据领域优秀代…

自然语言大模型介绍

1 简介 最近一直被大语言模型刷屏。本文是周末技术分享会的提纲,总结了一些自然语言模型相关的重要技术,以及各个主流公司的研究方向和进展,和大家共同学习。 2 Transformer 目前的大模型基本都是Transformer及其变种。本部分将介绍Transf…

FPGA基于XDMA实现PCIE X4的HDMI视频采集 提供工程源码和QT上位机程序和技术支持

目录1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案5、vivado工程详解6、驱动安装7、QT上位机软件8、上板调试验证9、福利:工程代码的获取1、前言 PCIE(PCI Express)采用了目前业内流行的点对点串行连接,比起 PCI …

自动化测试用什么框架?Pytest框架 vs Unittest框架,企业使用分析......

目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 安装方式不同 unit…

JavaWeb开发 —— 分层解耦

目录 一、三层架构 二、分层解耦 三、IOC & DI 入门 四、IOC控制反转详解 五、DI依赖注入详解 一、三层架构 在 JavaWeb开发 —— 请求响应 最后案例中我们编写的程序代码都是写在 Controller 当中。 而在我们实际软件设计和开发中,会尽量让每一个接口、类…

c++学习之类与对象2

目录 1.explicit关键字 类的对象数组 动态对象的创建与初始化 1.动态创建的概述 2.c语言方式创建动态对象 c对象的动态申请 1.new创建动态对象 2.delete释放动态对象 动态对象数组 静态成员 静态成员变量 静态成员函数 1.explicit关键字 explicit关键字 修饰构造函数…

查询淘宝商品详情页面数据(商品详情数据,商品销量数据,商品sku数据,商品视频数据,商品优惠券数据)接口代码封装教程

业务场景:作为全球最大的 B2C 电子商务平台之一,淘宝天猫平台提供了丰富的商品资源,吸引了大量的全球买家和卖家。为了方便开发者接入淘宝天猫平台,淘宝天猫平台提供了丰富的 API 接口,其中历史价格接口是非常重要的一…

策略设计模式(Strategy Pattern)[论点:概念、组成角色、相关图示、示例代码、适用场景]

文章目录概念组成角色相关图示示例代码适用场景概念 策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以相互替换。策略模式使得算法可以独立于使用它的客户端变化…

4.12~4.13学习总结

File 相对路径和绝对路径的区别: 相对路径不带盘符,绝对路径带盘符 小知识点:1KB1024字节,1MB1024KB,1GB1024MB; File对象就表示一个路径,可也是文件的路径,也可以是文件夹的路径 这个路径可以是存在的也可…

API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL丢失怎么解决?

API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL是Windows系统中的一个非常重要的动态链接库文件,该文件的全称为“Application Programming Interface Microsoft Windows C Runtime Link Library”。这个DLL文件中包含多个函数库,可将这些函数库链接到应用程序中。在…

AC7811-FOC无感控制代码详解

目录 矢量控制原理 矢量控制框图 电流采样方式 电流在整个控制过程中的传递 采样关键点 三电阻 双电阻 单电阻 三者对比 坐标变换 dq轴电流的PI控制 启动方式 启动波形 脉冲注入 高频注入 Startup 预定位到指定角度 PulseInject_api hfi_api Speed loop s…

已解决:ModuleNotFoundError: No module named ‘flask._compat‘

📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域新星创作者。😜🎉 支持我:点赞👍+收藏⭐️+留言📝📣 系列专栏:flask框架从入门到实战🍁💬格言:要成为光,因为有怕黑的人!🔥 相信很多人在flask项目中都遇到了这个报错:ModuleNotFoundError: No …

MyBatis动态SQL的使用

为什么需要使用动态sql? 在实际项目的开发中,开发人员在使用JDBC或其他持久层框架进行开发时,经常需要根据不同的条件拼接SQL语句,拼接SQL语句时还要确保不能遗漏必要的空格、标点符号等,这种编程方式给开发人员带来了非常大的不…

初探JdbcTemplate操作

文章目录一、创建数据库二、创建用户三、打开Spring项目四、添加数据库相关依赖五、创建用户实体类六、创建用户数据访问接口七、创建用户数据访问接口实现类八、创建用户服务类九、创建数据库配置属性文件十、创建Spring配置文件十一、创建用户服务测试类1、测试按编号查询用户…

Java 管道 (学习代码)

目录 上代码: 输出: 执行流程可以总结如下: 上代码: package cn.net.cdsz.ccb.test;import java.io.IOException; import java.io.PipedReader; import java.io.PipedWriter;public class test {static class ReaderThread imp…

C++回溯算法---图的m着色问题01

C回溯算法---图的m着色问题 图的m着色问题是指给定一个图以及m种不同的颜色,尝试将每个节点涂上其中一种颜色,使得相邻的节点颜色不相同。这个问题可以转化为在解空间树中寻找可行解的问题,其中每个分支结点都有m个儿子结点,最底层…

Flink、Hudi技术选型

Flink CDC 2.2的优势 相比Flink1.x,2.x的版本有如下的特点: 1) 并发读取,全量数据的读取性能可以水平扩展。 2) 全程无锁,不对线上业务产生锁的风险。 3) 断点续传,支持全量阶段的 Checkpoint。 Flink SQL的优势 …

MongoDB学习

文章目录前言0 MongoDB和Redis区别1 简介MongoDB2 MongoDB的安装(需要使用Docker)3 MongoDB 概念解析3.1 数据库3 .2 文档3.3 集合3.4 MongoDB 数据类型3.5适用场景4 常用操作4.1 INSERT4.2 Query4.3 Update4.4 Remove4.5 aggregate4.6 索引5 整合Springboot使用5.1 导入依赖5.…