Linux 文件、重定向、缓冲区

news2024/9/22 13:26:24

个人主页:仍有未知等待探索-CSDN博客

专题分栏: Linux

目录

一、文件

1、文件的理解(浅层)

1.文件是什么?

2.文件操作的前提

3.文件的存储 

4.一个进程可以打开多个文件吗?如果可以怎么管理的? 

5.打开文件(fopen用法)

​编辑

选项‘w‘:

选项’a‘:

6、输出重定向

重定向:

追加重定向:

2、文件的理解(深层)

1.文件操作

本质:

底层逻辑: 

2.认识系统调用和文件操作

1、文件描述符fd

标准输出和标准错误都是向显示器中打印数据,他们俩有什么区别?

打开多个文件的时候,怎么存储在struct file_struct* fd_array[N]数组里面?

文件操作符表的分配规则?

2、打开(并创建)文件open

参数:

​编辑

返回值:

底层逻辑:

3、关闭文件close

参数:

返回值:

4、写入文件write

5、读文件read

返回值:

3.理解Linux一切皆文件

4.C语言中文件类型FILE

二、重定向和缓冲区

1、重定向

1.本质

2.重定向的理解

 3.重定义符号‘>’

2、缓冲区

1.stat:系统调用

参数:

2.缓冲区

为什么打印的时候不进行刷新就没有显示?

什么是缓冲区?

为什么要有缓冲区?

缓冲区是怎么刷新的?

a、提高刷新策略。

b、特殊情况。

C语言为什么要在FILE中提供用户级缓冲区?

为什么需要fd == 1、2?

 perror和printf的区别?

文件和缓冲区的关系


一、文件

1、文件的理解(浅层)

1.文件是什么?

文件 = 属性 + 内容。

2.文件操作的前提

程序运行是文件操作的前提。

文件操作就是cpu在执行代码,本质就是进程在操作文件。

3.文件的存储 

文件在没有打开的时候:文件的属性和内容存储在磁盘上。

文件打开的时候:文件的属性存储在内存里,文件的内容按需加载到内存中。

4.一个进程可以打开多个文件吗?如果可以怎么管理的? 

一个进程可以打开多个文件。

管理的本质就是先描述,在组织。

管理一个文件:为了能更好的描述文件,os内部会用一个结构体来记录文件的各种属性,结构体内部会有一个指针指向一个文件缓冲区,里面存储着文件的内容。

管理一堆文件:将每个文件所对应的结构体用一个数组进行存储。

5.打开文件(fopen用法)

选项‘w‘:

以 ’写‘ 的方式打开文件。

1、如果该文件不存在,就在当前路径下,新建一个文件。

2、默认打开的时候,会把目标文件清空。

选项’a‘:

以 ’追加‘ 的方式打开文件。

1、 默认打开的时候,不会把目标文件清空,而是在文件内容的后面进行追加。

6、输出重定向

重定向:

echo “aaa” > log.txt

  • 重定向一定是文件操作。
  • 以 ’w‘ 的方式打开文件。
追加重定向:

echo “aaa” >> log.txt

  • 追加重定向一定是文件操作。
  • 以 'a' 的方式打开文件。

2、文件的理解(深层)

1.文件操作

本质:

进程和文件的交互关系。

底层逻辑: 

---> 想要对文件进行操作。

---> 去磁盘中寻找文件(找到以指定方式打开,找不到则新建文件)。

---> 对其进行打开操作,然后需要外设对其进行输入或者输出操作。

---> 向文件进行写入,本质上是向硬件中写入。

---> os是硬件的管理者,用户没有权限对其进行修改。

---> 所以os提供了一系列的系统调用。

---> fopen/fwrite/fread/fpintf/scanf/printf/cin/cout都是对系统调用的封装。

2.认识系统调用和文件操作

1、文件描述符fd

文件描述符fd的本质就是存储文件信息的数组下标。

下面这个3个文件都是默认打开的。

fd == 0:标准输入,键盘 --- stdin。

fd == 1:标准输出,显示器 --- stdout。

fd == 2:标准错误,显示器 --- stdout。

标准输出和标准错误都是向显示器中打印数据,他们俩有什么区别?

在打印信息的时候,可以将标准输出和标准错误进行分离。

打开多个文件的时候,怎么存储在struct file_struct* fd_array[N]数组里面?

找到没有存储文件且下标最小的位置。

文件操作符表的分配规则?

查自己(进程)的文件操作符表,分配最小的没有被使用文件操作符fd。

由图可知:无论是读文件还是写文件,都将文件内容从磁盘中读取到文件级缓冲区中。

2、打开(并创建)文件open

参数:

pathname:

a.如果传的是路径,则在指定路径下打开文件。若没有该文件,则以指定方式,新建文件。

b.如果传的是文件名,则在当前路径下打开文件。若没有,则以指定方式,新建文件。

flags:

32位比特位,是指定打开文件的方式(有很多的系统的选项)。

O_WRONLY --- 只写

O_CREAT --- 创建

O_TRUNC --- 清空

O_APPEND --- 追加

O_RDONLY --- 只读

// 以只写、追加的方式打开文件,当当前路径没有文件时,创建文件;若有文件,则打开文件
int fd1 = open("test.txt", O_WRONLY | O_CREAT |O_APPEND, 0666);

// 以只写、追加的方式打开文件,当当前路径没有文件时,不处理;若有文件,则打开文件
int fd2 = open("test.txt1", O_WRONLY | O_APPEND, 0666);
// 原理flags
// 这样就完成了各种选项的筛选

#include <stdio.h>

#define O_WRONLY (1)
#define O_CREAT (1 << 1)
#define O_APPEND (1 << 2)
#define O_RDONLY (1 << 3)
#define O_TRUNC (1 << 4)

void func(int flags)
{
    if (flags & O_WRONLY)
        printf("O_WRONLY\n");
    if (flags & O_CREAT)
        printf("O_CREAT\n");
    if (flags & O_APPEND)
        printf("O_APPEND\n");
    if (flags & O_RDONLY) 
        printf("O_RDONLY\n");
    if (flags & O_TRUNC)
        printf("O_TRUNC\n");

    printf("\n");
}
int main()
{
    func(O_WRONLY);
    func(O_WRONLY | O_CREAT);
    func(O_WRONLY | O_CREAT | O_APPEND);
    func(O_WRONLY | O_CREAT | O_APPEND | O_RDONLY);
    func(O_WRONLY | O_CREAT | O_APPEND | O_RDONLY | O_TRUNC);

    return 0;
}

mode:

如果有O_CREAT选项,并且在指定路径下,文件不存在,则新建文件的权限就是mode。

最终的文件权限 = ~unmark & mode

返回值:

返回的是打开文件或者新建文件的文件描述符fd。

底层逻辑:
  • 创建file。
  • 开辟文件缓冲区的空间,加载文件数据(延后加载、按需加载)。
  • 查进程中的文件描述符表。
  • 将 file 的struct_file的地址存入文件描述符表中。
  • 返回下标。
3、关闭文件close

参数:

fd 就是你要关闭的文件的fd。

返回值:

如果关闭成功,则返回 0 ;

如果关闭失败,则返回-1,并且设置了错误码errno。

4、写入文件write

将大小为 count 的 buf 里面的内容,写入到 fd 文件里面。

5、读文件read

从 fd 中 读数据,存储到buf中,count为能读取的最大字节数,即buf所指向的空间大小。

返回值:

返回值大于零,则代表实际读了多少字节。

3.理解Linux一切皆文件

对于fd == 0、1、2分别对应着不同的硬件,但是硬件是怎么和文件相关联上的呢?

4.C语言中文件类型FILE

建议使用的时候用语言层面的函数,即标准库函数。因为在不同的平台下面,系统调用的用法不一定相同。

FILE是一个C语言提供的结构体,里面一定封装了 fd 文件描述符。

FILE* fp = fopen("log.txt", "w");
// fp 里面封装了 fd:fp->fileno
// "w" == O_WRONLY | O_CREAT | O_TRUNC

二、重定向和缓冲区

1、重定向

1.本质

是在内核中改变文件描述符表特定下标的内容 和上层无关

2.重定向的理解

dup2的本质就是文件描述符下标对应的内容拷贝。

---> 将newfd文件关闭,把oldfd文件描述符放入newfd中,具体的效果就是下列的图

对应printf函数,在底层就已经默认是对fd==1的位置的文件中进行打印。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    // 把显示器关闭
    int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC);
    dup2(fd, 1);

    printf("I am test.c");

    return 0;
}

 3.重定义符号‘>’

格式:newfd > oldfd

2、缓冲区

1.stat:系统调用

stat系统调用的作用是:获取文件或者目录的状态信息(文件的各种属性)

参数:

struct stat* buf:是一种输出型参数。指向的是存储文件属性的结构体。

off_t st_size:文件的大小(字节)

2.缓冲区

为什么打印的时候不进行刷新就没有显示?

struct FILE* 这个结构体里有语言级别的文件缓冲区。

fflush()的作用是:将语言级别的缓冲区刷新到操作系统里面的内核文件缓冲区。

什么是缓冲区?

缓冲区就是一段内存空间。

为什么要有缓冲区?

给上层空间提供高效的IO体验,间接提高整体的效率。

缓冲区是怎么刷新的?
a、提高刷新策略。

立即刷新。fflush(stdout):用户级到内核级缓冲 区、fsync(int fd):内核级缓冲区到外设

行刷新。是为了照顾用户的习惯 --- 显示器

全缓冲。缓冲区写满才刷新。--- 普通文件

b、特殊情况。

进程退出,系统会自动刷新。

强制刷新。

C语言为什么要在FILE中提供用户级缓冲区?

为了减少底层调用系统调用的次数,让使用C语言的IO函数效率更高。

为什么需要fd == 1、2?

我们写的程序,本质都是对数据在进行处理(计算、存储),所以我们需要知道处理时候发生异常的原因。

打印到显示器的里面的信息,可能是正确的,可能是错误的。1、2都是往显示器中打印,这样的话,在文件层面,正确信息和错误信息就分开了,./a.out 1> log.txt 2> err.txt。 

 perror和printf的区别?

perror本质上是向2打印,而printf本质上是向1打印。

文件和缓冲区的关系

每一个文件都有自己的缓冲区和文件操作符表。

每个进程在操作系统中通过文件描述符来访问文件,并且这些访问可能涉及到由操作系统或应用程序库管理的文件缓冲区。

谢谢大家!!!

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

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

相关文章

【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式

文章目录 webView使用步骤示例 HttpURLConnection使用步骤示例GET请求POST请求 okHttp使用步骤1. 添加依赖2. 创建OkHttpClient实例3. 创建Request对象构建请求4. 发送请求5. 获取响应 Pull解析方式1. 准备XML数据2. 创建数据类3. 使用Pull解析器解析XML webView WebView 是 An…

三大浏览器Google Chrome、Edge、Firefox内存占用对比

问题 Chrome、Edg、Firefox三家究竟谁的占用少 结论 打开一个页面内存占用 Firefox>Edge>Chrome 打开打量页面内存占用 Firefox>Chrome>Edge 从监视器可以看到Edge增加一个页面增加一个页面不到100M而其它浏览器需要150M左右;Firefox浏览器主线程内存占用800M比…

Java之TCP网络编程

TCP网络编程 1 概述 在TCP通信协议下&#xff0c;计算机网络中不同设备上的应用程序之间可以通信&#xff0c;通信时需严格区分客户端&#xff08;Client&#xff09;与服务器端&#xff08;Server&#xff09;。 在Java中&#xff0c;对于这样基于TCP协议下连接通信的客户端…

数据结构-常见排序的七大排序

1.排序的概念及其运用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录…

Arkose 验证码:网络抓取工具的最佳实践

网络爬虫已经成为企业和开发人员最常用的工具&#xff0c;用于有效地从网络中收集数据。当然&#xff0c;大家都会遇到的最常见挑战是大量的 CAPTCHA 出现&#xff0c;这会使工作流程陷入停滞。其中&#xff0c;Arkose Labs Captcha&#xff08;称为 Funcaptcha&#xff09;以其…

探索N卡录制:游戏录屏工具会是网页录屏的最佳伴侣吗?

在这个数字时代&#xff0c;无论是游戏玩家、教育工作者还是内容创作者&#xff0c;高质量的录屏工具都是必不可少的。NVIDIA显卡&#xff08;简称N卡&#xff09;以其卓越的图形处理能力而闻名&#xff0c;而N卡录制功能则进一步扩展了其应用范围&#xff0c;特别是在游戏录屏…

【SpringBoot 属性加载机制】

SpringBoot 属性加载 一个 SpringBoot 应用的配置属性可以有多种不同的来源, 比如可以来自操作系统的环境变量, 比如可以来自 application.yaml 文件; 每一种不同的属性来源, 都会被 SpringBoot 封装成一个PropertySource对象, 保存在 Environment 对象的 PropertySources 类型…

proteus仿真c51单片机(三)多定时任务的编程——时分秒发生器

实验步骤 1、打开PROTEUS软件选取元件&#xff0c;连线绘制电路图。 2、打开KEIL软件编制程序进行调试、编译。 3、将编译的HEX代码装入PROTEUS软件绘制的电路图的单片机中。 4、仿真运行观察实验现象&#xff0c;若与要求的实验现象不同&#xff0c;检查程序和电路图找…

Linux目录结构常用命令和文件管理解析

一.Linux目录结构 bin:binary二进制&#xff0c;普通用户执行命令都在这里 boot:和计算机启动的相关文件都放这 dev:device设备、驱动、硬件 etc:配置文件也叫控制台文件 home:来装用户自己的文件的&#xff0c;普通用户的家目录主目录&#xff0c;每个普通用户进来都有自…

PythonStudio 控件使用常用方式(十二)TMaskEdit

PythonStudio是一个极强的开发Python的IDE工具&#xff0c;它使用的是Delphi的控件&#xff0c;常用的内容是与Delphi一致的。但是相关文档并一定完整。现在我试试能否逐步把它的控件常用用法写一点点&#xff0c;也作为PythonStudio的参考。 从1.2.1版开始&#xff0c;Python…

Android compose OutlinedTextField 输入框设置固定高度后,内容挤压显示不全

原因&#xff1a; decorationBox里边contentPadding() 默认为16.dp internal val TextFieldPadding 16.dp 修改方法1&#xff1a; copy OutlinedTextField.kt 源码&#xff0c;decorationBox的contentPadding参数开放出来 /*** author 创建人&#xff1a;蒙石瑞* date …

【大模型从入门到精通11】openAI API 提示链的力量2

这里写目录标题 提示链的力量&#xff1a;阅读和处理JSON字符串基于产品信息生成用户响应综合性的客户服务互动结论理论问题 提示链的力量&#xff1a;阅读和处理JSON字符串 当处理复杂的工作流程时&#xff0c;通常会以JSON格式传递数据。以下示例演示了如何将JSON字符串转换…

【Linux QT】添加Json-C库

前言 在Linux应用开发中&#xff0c;Linux设备和服务器通信时&#xff0c;两者之间数据的传输通常采用JSON数据格式来作为载体&#xff0c;便于两者之间的数据交互。当设备端接收到服务端下发的JSON数据&#xff0c;设备端需要对JSON格式的数据进行解析&#xff1b;当设备端需要…

Java设计模式(命令模式)

定义 将一个请求封装为一个对象&#xff0c;从而让你可以用不同的请求对客户进行参数化&#xff0c;对请求排队或者记录请求日志&#xff0c;以及支持可撤销的操作。 角色 抽象命令类&#xff08;Command&#xff09;&#xff1a;声明用于执行请求的execute方法&#xff0c;通…

CSS实现hover时文本上下出现线条

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>复杂Hover效果示例</title><style>p {f…

【案例38】Can’t get connection from database 排查详细记录

问题现象 客户要搭建灰度环境&#xff0c;启动后&#xff0c;登录超级管理员报连接不上数据库的错误。 Can’t get connection from database(XXX) 问题分析 1、一般碰到这个问题&#xff0c;初步就开始怀疑是sysconfig数据源不通导致的。 发现数据源是通的。 2、在sysconf…

【案例40】Apache中mod_proxy模块的使用

NC中间件 应用场景&#xff1a;配置了apache的情况&#xff0c;包括uap集群&#xff0c;配置https等场景下均适用&#xff1b;如果是单机&#xff08;NC单结点情况不存在问题&#xff0c;则不用配置这项; was环境也不用配置此项。&#xff09; 解决方案&#xff1a;按如下两…

【15.PIE-Engine案例——加载Landsat 8 SR数据集】

加载Landsat 8 SR数据集 原始路径 欢迎大家登录航天宏图官网查看本案例原始来源 最终结果 具体代码 /*** File : Landsat8SRImages* Time : 2020/7/21* Author : piesat* Version : 1.0* Contact : 400-890-0662* License : (C)Copyright 航天宏图信息技…

【C++】BFS解决Floodfill问题

目录 Floodfill算法介绍 解决方法 BFS 图画渲染 算法思路&#xff1a; 代码实现&#xff1a; 岛屿数量 算法思路 代码实现 岛屿的最大面积 算法思想 代码实现 被围绕的区域 算法思路 代码实现 总结&#xff1a; Floodfill算法介绍 Floodfill翻译过来就是“洪…

serial靶机渗透~反序列化

反序列化又叫对象注入&#xff0c;序列化在内部没有漏洞&#xff0c;漏洞产生是因为程序在处理对象、魔术函数以及序列化相关的问题导致的&#xff0c;当传给 unserialize()的参数可控时&#xff0c;那么用户就可以注入 payload&#xff0c;进行反序列化的时候就可能触发对象中…