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

文章目录

  • 一、文件的读写操作
  • 二、文件描述符
  • 三、文件重定向
  • 四、理解 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.mzph.cn/diannao/46157.shtml

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

相关文章

《python程序语言设计》2018版第5章第55题利用turtle黑白棋盘。可读性还是最重要的。

今天是我从2024年2月21日开始第9次做《python程序语言设计》作者梁勇 第5章 从2019年夏天的偶然了解python到2020年第一次碰到第5章第一题。彻底放弃。再到半年后重新从第一章跑到第五章&#xff0c;一遍一遍一直到今天2024.7.14日第9次刷第五章。 真的每次刷完第五章感觉好像…

【JavaScript】解决 JavaScript 语言报错:Uncaught SyntaxError: Unexpected token

文章目录 一、背景介绍常见场景 二、报错信息解析三、常见原因分析1. 缺少必要的语法元素2. 使用了不正确的字符或符号3. JSON 格式错误4. 字符串未正确闭合 四、解决方案与预防措施1. 检查语法元素2. 正确使用符号和字符3. 修正 JSON 格式4. 字符串闭合 五、示例代码和实践建议…

android13 文件管理器无法安装apk 奔溃问题

总纲 android13 rom 开发总纲说明 目录 1.前言 2.我们简单写个apk测试下 3.排查客户apk 4.frameworks源码排查 5.编译验证 6.彩蛋 1.前言 客户提供的文件管理apk不能安装apk文件,一点击就奔溃。 2.我们简单写个apk测试下 private void installApk(File apkFile) {i…

映美精黑白相机IFrameQueueBuffer转halcon的HObject

映美精黑白相机&#xff0c;用wpfhalcon开发取图 1.到官网下载&#xff0c;开发包 1sdk 2c开发例子 3c#开发例子 引入TIS.Imaging.ICImagingControl35.dll 3.ICImagingControl使用这个类控制相机 /// <summary> /// 相机控制 /// </summary> public ICImagingC…

MySQL的插入(DML)

1.给指定字段添加数据 这个就是&#xff0c;想插入所对应的字段&#xff0c;就插入所对应的数值。先把字段列出来&#xff0c;不一定是全部的字段&#xff0c; 然后插入想要的值&#xff0c;注意&#xff0c;只能插入一行。 INSERT INTO 表名 (字段1,字段2,.....) VALUES(值…

将swagger注解导入apifox的IDEA配置

在使用IDEA开发中&#xff0c;经常需要将后端接口导出到Apifox&#xff0c;以便于测试。将swagger注解内容导出到Apifox中&#xff0c;需要进行以下设置: file->settting打开对话框&#xff0c;选择Other Settings -> Apifox Help&#xff0c;如下图&#xff1a; 2.选…

【软件测试】自动化测试常用函数 -- 详解

一、WebDriver API 一个简单自动化脚本的构成&#xff1a; 脚本解析 # coding utf-8 from selenium import webdriver import time browser webdriver.Firefox() time.sleep(3) browser.get("http://www.baidu.com") time.sleep(3) browser.find_element_by_id(…

数据实时化是必要还是偏见?

数据实时化是必要还是偏见&#xff1f; 一、前言二、数据仓库的起源三、数据架构的演进四、数据实时化的必要性五、总结 本文主要基于数据仓库的起源和数据架构的演进来聊聊&#xff0c;数据实时化是否真的必要&#xff1f;是"过度优化"、“实时偏见"还是"…

【数据结构】手写快速排序

一、理念 什么是快速排序&#xff1f; 首先确立pivot&#xff0c;比如下图位于末尾 然后i遍历3到6 在3的时候&#xff0c;j指向i前面一位 如果3<5(pivot)&#xff0c;那么j&#xff0c;同时将i与j指向的交换&#xff0c;第一次交换是原地不动 一直到遇见9&#xff0c;…

数据结构和算法(0-1)----递归

定义​ 递归是一种在程序设计中常用的技术&#xff0c;它允许一个函数调用自身来解决问题。递归通常用于解决那些可以被分解为相似的子问题的问题&#xff0c;这些问题的解决方式具有自相似性。在数据结构和算法中&#xff0c;递归是一种重要的解决问题的方法&#xff0c;尤其是…

处于群晖Docker中的HomeAssistant监控宿主机CPU温度

处于群晖Docker中的HomeAssistant监控宿主机CPU温度 解决方案 在configuration.yaml中添加&#xff1a; sensor: - platform: filename: "Host Temperature" # 可以自定义file_path: /sys/class/hwmon/hwmon0/temp1_inputvalue_template: "{{ int(value)/100…

taro小程序terser-webpack-plugin插件不生效(vue2版本)

背景 最近在做公司内部的小程序脚手架&#xff0c;为了兼容老项目和旧项目&#xff0c;做了vue2taro,vue3taro两个模板&#xff0c;发现terser-webpack-plugin在vue2和vue3中的使用方式并不相同&#xff0c;同样的配置在vue3webpack5中生效&#xff0c;但是在vue2webpack4中就…

sql monitoring 长SQL ASH AWR 都没有 未Commit or export to csv

Duration 4小时&#xff0c; Database Time 22.5&#xff0c; Session Inactive&#xff0c; 1.未Commit原因, 2.慢慢导出成csv文件&#xff1f; How is v$session status INACTIVE and v$sql_monitor status EXECUTING concurrently 2641811 Posts: 8 Jan 11, 2016 6:47P…

git安装使用gitlab

第一步&#xff1a;下载git 第二步&#xff1a;安装 第三步&#xff1a;配置sshkey 第四步&#xff1a;处理两台电脑的sshkey问题 第一步下载git 网址&#xff1a;Git点Downloads根据你的操作系统选择对应的版本&#xff0c;我的是Windows&#xff0c;所以我选择了Windows …

Apple Intelligence将如何重新定义iPhone上的Siri使用方式|TodayAI

经过多年的讨论和批评&#xff0c;苹果&#xff08;Apple&#xff09;终于在今年秋季承诺推出更智能版本的数字助理Siri。此次更新得益于苹果智能&#xff08;Apple Intelligence&#xff09;&#xff0c;这是公司推出的生成式AI产品&#xff0c;并与OpenAI合作开发。 Siri将迎…

css画半圆画圆弧

利用border-radius和border完成&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>test</title> <style> .semicircle {width: 100px;height: 50px;border-radius: 0 0 50px 50px;background:…

springboot系列教程(一):简介与入门案例(含源码)

一、SpringBoot简介 SpringBoot继承了Spring优秀的基因&#xff0c;上手难度小简化配置&#xff0c;提供各种默认配置来简化项目配置内嵌式容器简化Web项目&#xff0c;简化编码 Spring Boot 则会帮助开发着快速启动一个 web 容器&#xff0c;在 Spring Boot 中&#xff0c;只…

【性能测试】第二节.loadrunner工具介绍(LR)

文章目录 前言一、VUG&#xff1a;虚拟用户发生器 1.1 实现作用 1.2 创建一个新的性能测试脚本 1.3 打开LR自带的web系统 1.4 编写性能测试脚本流程方法 1.5 性能测试脚本的增强二、Controller 2.1 基础功能介绍 2.2 Design 2.3 Run三…

手把手教你在Overleaf的IEEE模板中用ref.bib加入引用

手把手教你在Overleaf的IEEE模板中用ref.bib加入引用 文章目录 1. 杂话2. 具体步骤2.1 创建ref.bib文件2.2 加入引用2.3 在tex文件中导入引用 1. 杂话 大伙儿应该都用过Latex和Overleaf吧&#xff0c;具体是个啥东西我就不说了哈。Overleaf上面的在这里IEEE 会议官方模板。之前…

安防监控视频平台LntonCVS视频融合共享平台智慧消防实现远程集中视频监控方案

近年来&#xff0c;电力系统内变电站着火事件频发&#xff0c;这对消防安全管理提出了严峻挑战。我国消防安全基础设施不完善、管理机制不健全、应急处置能力不足及公众消防安全意识淡薄等问题&#xff0c;严重制约了消防安全的提升。因此&#xff0c;加强变电站的消防安全管理…