【Linux 文件读写描述符重定向 Linux 一切皆文件缓冲区】

news2024/9/25 1:19:16

文章目录

  • 一、文件的读写操作
  • 二、文件描述符
  • 三、文件重定向
  • 四、理解 Linux 一切皆文件
  • 五、文件缓冲区

一、文件的读写操作

文件=内容+属性
当文件没有被操作的时候,一般文件还是在磁盘当中
文件操作=文件内容的操作+文件属性的操作,文件操作有可能即改变内容,又改变属性
文件操作其实就是把内容和属性加载到内存当中

  文件的系统调用函数一般有以下几个参数,pathname(对应文件路径),flags(文件打开方式),mode(指定文件的权限)。这里的 flags 不能简单当作一个整型来看,而且应该把它当作一个位图,32个 bit 位对应32种状态。打开文件时,可以传入多个参数选项,用下面的一个或者多个宏进行 “或” 运算,构成flags,调用类似下面的 show(ONE | TWO | THREE)

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
flags参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_TRUNC:初始化清空文件
O_APPEND: 追加写

#define ONE (1<<0)   // 1                                                                                                                  
#define TWO (1<<1)   // 2  
#define THREE (1<<2) // 4  
#define FOUR (1<<3)  // 8 
void show(int flags)  
{  
    if(flags&ONE) printf("func1\n");  
    if(flags&TWO) printf("func2\n");  
    if(flags&THREE) printf("func3\n");  
    if(flags&FOUR) printf("func4\n");  
    //………
} 

  文件操作其实就是一系列的系统调用,调用系统提供的函数。就算是语言层面的操作文件函数,也只是在内部封装了 open、write、read 等系统函数。因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过 fd(文件描述符) 访问的。所以C库当中的 FILE 结构体内部,必定封装了 fdC/C++ 封装的库函数中对文件打开方式主要有以下几种:

FILE * fopen ( const char * filename, const char * mode )
mode参数:
b:以二进制模式打开文件
r&r+:前者以只读方式打开,后者以读写方式打开文件.文件必须存在,否则打开失败
w&w+:前者以写入方式打开,后者以读写方式打开文件.若文件不存在,则创建新文件。存在,则清空文件内容
a: 以追加写入方式打开文件,若文件不存在,则创建新文件。写入的数据总是添加到文件的末尾
a+:以读写追加方式打开文件,若文件不存在,则创建新文件。可以从文件的任何位置读取数据,写入的数据总是添加到文件的末尾

二、文件描述符

  要对文件进行系统的管理,必须先描述再组织。当一个进程打开一个文件时,内核会创建一个 struct file 结构来存储关于这个文件的所有信息,包括:

文件在磁盘上的位置;文件的基本属性,如权限、大小;
文件的读写位置(文件偏移量);
文件的拥有者信息,即哪个进程打开了该文件;
文件的内核缓冲区信息等;

  task_struct 结构体里面的成员:struct files_struct,用于管理一个进程打开的所有文件。它包含: 一个文件描述符表 fd_array,这是一个数组,其元素是指向 struct file 的指针,每个元素对应一个打开的文件。文件描述符(FD)是这个数组的索引,每个索引唯一地标识了一个打开的文件。文件描述符是一个非负整数,0,1,2默认被占用为标准输入,标准输出和标准错误三个文件,即我们创建文件的描述符都是从3以后开始。当进程关闭文件时,会减少 struct file 的引用计数。如果引用计数变为0,内核会释放 struct file 实例,并清理相关资源。

文件的简单管理结构如下:

三、文件重定向

  文件重定向的本质是修改文件描述符表 fd_array 中的 FD 对应的 struct file* 地址。即文件描述符 FD(0,1,2,3) 等不变,改变 struct file* 的值,使它指向不同的文件

dup2 系统调用实现重定向:

#include <unistd.h>
int dup2(int oldfd, int newfd);

  dup2 函数的作用是将 oldfd 指向的文件地址覆盖 newfd 指向的文件地址,如果 newfd 指向的文件已经打开,则会先关闭 newfddup2 函数可以使不同文件描述符可以指向同一个文件,如下图:

四、理解 Linux 一切皆文件

  操作系统是一款管理软件,它通过向下管理好各种软硬件资源 (手段),来向上提供良好 (安全、稳定、高效) 的运行环境 (目的)。对键盘、显示器、磁盘、网卡等硬件进行管理需要先描述、再组织:即先将这些设备的各种属性抽象出来组成一个结构体,然后为每一个设备都创建一个结构体对象,再用某种数据结构将这些对象组织起来,这也就是我们上面学习到的文件内核数据结构 file
  由于每种硬件的访问方法都是不一样的,我们需要为每一种硬件都单独提供对应的 Read、Write 等方法,这些方法位于驱动层。参考下图:
  struct file 中定义函数指针 read()write() 方法 ,而这些方法在驱动层被实例化,指向不同硬件的访问方法。这是一种多态行为。即使用户使用相同的系统调用接口,实际执行的操作会根据底层文件或设备的类型而变化。file 结构体可以类似于 C++ 中的基类,驱动层的各种方法和结构就相当于子类,可以看作它们继承了基类,同时又扩充了对底层硬件管理的特殊方法。站在操作系统内核数据结构上层来看,所有的软硬件设备和文件统一都是 file 对象,它是操作系统当中虚拟出来的一层文件对象,我们将这一层称为 虚拟文件系统 VFS,通过它,我们就可以摒弃掉底层设备的差别,统一使用文件接口的方式来进行文件操作,即 Linux 下一切皆文件!

五、文件缓冲区

  缓冲区分为用户级缓冲区和内核级缓存区,我们所接触到的缓冲区大部分都属于用户级语言缓冲区。文件也有自己的缓冲区,被描述为 FILE 结构体中的一个字段,类似 char buff [size]。而我们常说的刷新缓冲区就是指缓冲区里的数据加载(拷贝)到内核缓冲区,而文件是被进程管理的,进程退出时与文件描述符相关联的内核缓冲区会被刷新到磁盘上。
缓冲区刷新常见策略:

1、无缓冲(立即刷新) :缓冲区中一出现数据就立马刷新,这种很少出现;
2、行缓冲(行刷新 ):遇到换行符(\n)数据就刷新一次
3、全缓冲(缓冲区满刷新):待数据把缓冲区填满后再刷新,这种刷新方式效率最高,一般应用于磁盘文件

  显示器采用的刷新策略是行缓冲,与此相对,普通文件采用的刷新策略是全缓冲。显示器是给人看的,按行刷新符合人的阅读习惯,而普通文件更多需要全缓存来提高效率。
  系统调用接口 write 是直接往内核缓存区里写,如 C库中的 fwrite 是往文件缓冲区里面写,当文件缓冲区刷新时,再把文件缓冲区里的数据加载(拷贝)到内核缓冲区。下面通过两个例子来加深对缓冲区的理解;

例一:
  两张图片中都关闭了1号标准输出文件,但是左图把信息全部打印出来了,而右图只打印了系统调用 write,因为显示器文件是行刷新,左图 fwrite 加了换行符 \n的信息已经从文件缓冲区拷贝到了内核缓冲区,被显示出来。而右图没有加换行符 \n,关闭了文件描述符后,文件缓冲区的信息没有加载到内核缓冲区中,因此右边的 fwrite 信息消失不见。write 系统调用是直接往内核缓冲区写的,因此左右图都会打印 write 信息


例二:
  由上面我们知道,文件缓冲区被描述为 FILE 结构体中的一个字段,那么当我们 fork 创建子进程时,子进程会拥和父进程一样的文件描述符表及其缓冲区。当我们向显示器打印时,按行刷新。fork 时,此时父进程的文件缓冲区为空,信息已经刷新到了内核缓冲区中。此时子进程虽然拥有和父进程一样的文件缓冲区,但却是空的,因此显示结果如左边。当我们重定向到普通文件打印时,为全缓冲,fork 时,父进程文件缓冲区有 fwrite 信息,因此 fork 之后子进程的文件缓冲区也有 fwrite 信息,最终导致 fwrite 打印了两次,而 write 打印在前面是因为它直接写入了内核缓冲区,不用像 fwrite 一样刷新了才加载到内核缓冲区

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

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

相关文章

实战:docker式部署frp内网穿透-2024.7.13(测试成功)

前提 首先就需要准备好一台云服务器&#xff0c;用于提供公网 IP 和流量转发。至于购买哪家的云服务产品&#xff0c;本着能省则省的原则&#xff0c;这个当然是哪家便宜用哪家呢。 我手上目前有闲置的腾讯云的服务器&#xff0c;刚好可以用来作为内网穿透的机器&#xff0c;…

MySQL篇十:事务

文章目录 前言1. 什么是事务&#xff1f;2. 为什么会出现事务3. 事务的版本支持4. 事务提交方式5. 事务常见操作方式6. 事务隔离级别6.1 如何理解隔离性16.2 如何理解隔离性26.2.1 读-写6.2.2 undo 日志6.2.3 模拟 MVCC6.2.4 RR 与 RC的本质区别 前言 CURD不加控制&#xff0c;…

【探索Linux】P.39(传输层 —— TCP的三次 “握手” 和四次 “挥手” )

阅读导航 引言一、TCP的三次握手1. 简介2. 图解三次握手3. 名词解释&#xff08;1&#xff09;SYN&#xff08;同步序列编号&#xff09;包&#xff08;2&#xff09;SYN-ACK&#xff08;同步确认&#xff09;包&#xff08;3&#xff09;ACK&#xff08;确认&#xff09;包 4.…

【CTF-Crypto】数论基础-02

【CTF-Crypto】数论基础-02 文章目录 【CTF-Crypto】数论基础-021-16 二次剩余1-20 模p下-1的平方根*1-21 Legendre符号*1-22 Jacobi符号*2-1 群*2-2 群的性质2-3 阿贝尔群*2-4 子群2-11 群同态2-18 原根2-21 什么是环2-23 什么是域2-25 子环2-26 理想2-32 多项式环 1-16 二次剩…

C语言的神髓

从应用的角度出发&#xff0c;聊一聊C语言最精妙的部分。 ​​​​​​​ ​​​​​​​

unity 2020版本packManager没有AssetBundles

1.Packages->manifest.json打开manifest.json文件 2.添加"com.unity.assetbundlebrowser": "1.7.0", 保存即可

Readiris PDF Corporate / Business v23 解锁版安装教程 (PDF管理软件)

前言 Readiris PDF Corporate / Business 是一款高性能的 OCR&#xff08;光学字符识别&#xff09;软件&#xff0c;能够帮助用户将纸质文档、PDF 文件或图像文件转换为可编辑和可搜索的电子文本。该软件提供专业级的功能和特性&#xff0c;非常适合企业和商业使用。使用 Rea…

win10 docker-compose搭建ELK日志收集

elk的威名大家都知道&#xff0c;以前前司有专门的人维护&#xff0c;现在换了环境&#xff0c;实在不想上服务器看&#xff0c;所以就摸索下自己搭建&#xff0c;由于现场服务器是需要类似向日葵那样连接&#xff0c;我还是把日志弄回来&#xff0c;自己本地filebeat上传到es中…

【软件测试】LoadRunner | 基本概念 | VUG录制脚本 | 脚本加强 | Controller设计测试场景 | Analysis产生测试报告

文章目录 LoadRunner一、LoadRunner的基本概念功能:原理&#xff1a;组成&#xff1a; 二、开发测试脚本1.VUG录制脚本1.WebTours系统WebTours的配置&#xff1a;成功访问后进行注册 2.脚本录制3.运行&#xff08;回放&#xff09; 2.脚本加强1.插入事务插入函数:注意事项 2.插…

如何计算摄像头一个像素对应的实际面积(热成像仪选型1)

1. 前言 热成像仪广泛应用于缺陷检测&#xff0c;那么如何选择热成像仪&#xff0c;以满足缺陷检测需求&#xff1f;关键问题是&#xff1a;如何知道热成像仪能不能拍摄清楚我的缺陷呢&#xff1f;&#xff0c;要回答这个问题&#xff0c;就需要计算出热成像仪在最佳拍摄距离下…

2.5 OJ 网站的使用与作业全解

目录 1 OJ 网站如何使用 1.1 注册账户 1.2 登录账户 1.3 做题步骤 2 本节课的 OJ 作业说明 3 章节综合判断题 4 课时2作业1 5 课时2作业2 6 课时2作业3 1 OJ 网站如何使用 〇J 是英文 Online Judge 的缩写&#xff0c;中文翻译过来是在线判题。当用户将自己编写的代码…

浪潮天启防火墙TQ2000远程配置方法SSL-V偏、L2xx 配置方法

前言 本次设置只针对配置V偏&#xff0c;其他防火墙配置不涉及。建议把防火墙内外网都调通后再进行V偏配置。 其他配置可参考&#xff1a;浪潮天启防火墙配置手册 配置SSLVxx 在外网端口开启SSLVxx信息 开启SSLVxx功能 1、勾选 “启用SSL-Vxx” 2、设置登录端口号&#xff0…

ROS1 DWB 与 ROS2 DWA 比较

“DWA算法(dynamic window approach)是移动机器人在运动模型下推算(v,w)对应的轨迹,确定速度采样空间或者说是动态窗口(三种限制);在速度空间(v,w)中采样多组速度,并模拟这些速度在一定时间内的运动轨迹,通过一个评价函数对这些轨迹打分,选取最优的轨迹来驱动机器人运动”。ROS…

如何利用桌面工作计划软件制定自己的to do清单?

在我们的日常生活和工作中&#xff0c;经常会遇到各种各样的任务需要完成。如果没有一个明确的计划和安排&#xff0c;我们可能会感到混乱和压力&#xff0c;而桌面工作计划软件可以帮助我们更好地管理和规划我们的时间和任务。今天&#xff0c;我们就来聊聊如何利用这些工具&a…

职升网:二级建造师考试科目分析!

二级建造师考试包含三个主要科目&#xff0c;它们分别是《建设工程施工管理》、《建设工程法规及相关知识》以及《专业工程管理与实务》。以下是这三个科目的详细考试内容&#xff1a; 建设工程施工管理&#xff1a; 此科目作为建造师考试的基础科目&#xff0c;其核心内容是…

走进linux

1、为什么要使用linux 稳定性和可靠性&#xff1a; Linux内核以其稳定性而闻名&#xff0c;能够持续运行数月甚至数年而不需要重新启动。这对于服务器来说至关重要&#xff0c;因为它们需要保持长时间的稳定运行&#xff0c;以提供持续的服务 安全性&#xff1a; Linux系统…

酷克数据亮相第13届PostgreSQL中国技术大会,获数据库杰出贡献奖

7 月 12 日&#xff0c;第 13 届 PostgreSQL 中国技术大会在杭州盛大开幕。本次大会以“聚焦云端创新&#xff0c;汇聚智慧共享”为主题&#xff0c;邀请了国内外 PG 领域众多行业大咖、学术精英及技术专家&#xff0c;共同探讨数据库领域的发展趋势、技术创新和实践经验。酷克…

本地部署,使用ColorizeArtistic_gen.pth大模型进行图像上色

目录 引言 技术背景 模型架构 本地部署 运行结果 实验结果与分析 应用实例 结论 参考文献 引言 图像上色&#xff08;Image Colorization&#xff09;是指将黑白图像转换为彩色图像的技术。在数字化时代&#xff0c;这种技术可以用于修复旧照片、增强艺术作品以及在各…

FDL与Kettle功能对比分析之定时任务DDL

开发者在进行数据处理任务时&#xff0c; 一旦源数据库的表结构发生变化&#xff0c;而目标数据库没有及时进行同步&#xff0c;就会导致任务执行失败。DDL同步就是用来解决这一问题&#xff0c;它会自动识别源表结构变化&#xff0c;并及时更新到目标数据库中&#xff0c;保障…

1. 变量、运算符、表达式、输入与输出习题

第一节题单 1. A B import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int a,b;a sc.nextInt();b sc.nextInt();System.out.println(ab);} }608.差 604. 圆的面积 注意不能用float,float的精度不够…