【Linux 】文件描述符fd、重定向、缓冲区(超详解)

news2024/10/7 12:04:00

目录

​编辑 系统接口进行文件访问

open 接口介绍

文件描述符fd

重定向

缓冲区

1、缓冲区是什么?

2、为什么要有缓冲区?

3、怎么办?


我们先来复习一下,c语言对文件的操作:

C默认会打开三个输入输出流,分别是stdin, stdout, stderr

  1 #include<stdio.h>
  2 
  3 int main()
  4 {
  5     FILE *fp=fopen("log.txt","w");
  6     if(fp==NULL)
  7     {
  8         perror("error!");
  9         return 1;
 10     }
 11     fprintf(fp,"hello,%d,%s\n",10,"sxh");
 12     fclose(fp);
 13     return 0;
 14 }

 系统接口进行文件访问

操作文件,除了上述C接口(当然,C++也有接口,其他语言也有),我们还可以采用系统接口来进行文件访问;

  #include<stdio.h>
  #include<string.h>
   
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>
  #include<unistd.h>
   
  int main()
  {
      umask(0);
      int fd =open("log.txt",O_WRONLY | O_CREAT |O_TRUNC,0666);
      if(fd<0)
      {   
          perror("open");
          return 1;
      }
      
      //const char *message ="hello Linux!\n";
      const char * message ="aaaa\n";
      write(fd,message,strlen(message));
  
      close(fd);
  }

open("log.txt",O_WRONLY | O_CREAT |O_TRUNC,0666);:以写方式打开,不存在就创建,存在就先清空!相当于c语言中的  “w”  方式;

open 接口介绍

open man 2 open

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

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode)
       int creat(const char *pathname, mode_t mode);

pathname:要打开或创建的目标文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成;  常见的参数有:

                        O_RDONLY: 只读打开

                        O_WRONLY: 只写打开
                        O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
                        O_APPEND: 追加写

mode: mode 只有 当 在 flags 中使用 O_CREAT 时才有效 , 否则被忽略.

返回值
                成功:新打开的文件描述符
                失败:-1

 

文件描述符fd

我们通过系统调用I/O打开一个文件的返回值,就是文件描述符:

int fd = open("log.txt",O_WRONLY | O_CREAT |O_TRUNC,0666);

这里fd就是log.txt的文件描述符;

如果我们同时打开三个文件,并把这三个文件的文件描述符打印出来,会发现:

文件描述符是从3开始的,那0、1、2呢?

Linux进程默认情况下会有3个缺省打开的文件描述符:分别是标准输入0, 标准输出1, 标准错误2.
0,1,2对应的物理设备一般是:键盘,显示器,显示器

根据上述的图,我们可以知道:

open干什么?

1、创建file

2、开辟文件缓冲区的空间,加载文件数据(延后)

3、查看进程的文件描述符表

4、file地址,填入对应的表下标中

5、返回下标

重定向

看一下下面的代码:

1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<unistd.h>
  6 #include<string.h>
  7 #include<stdlib.h>
  8 const char *filename="log.txt";
  9 
 10 int main()
 11 {
 12     //close(0);
 13     close(1);
 14     //close(2);
 15     int fd =open(filename,O_CREAT | O_WRONLY | O_TRUNC,0666);
 16     if(fd<0)
 17     {
 18         perror("open");
 19         return 1;
 20     }
 21     printf("printf,fd:%d\n",fd);
 22     fprintf(stdout,"fprintf,fd:%d\n",fd);
 23 
 24     fflush(stdout);
 25 
 26 
 27     close(fd);
 28     return 0;
 29 
 30 }

先看现象:

1、如果我们关闭的是0:打印出来的log.txt的文件描述符是0;关闭的是2,则打印出来的文件描述符是2;关闭的是1,则不会显示出来;因为文件描述符1表示的是显示器,而我们把显示器关掉了自然打印不出来;

2、我们会在log.txt中打印出printf和fprintf的内容:

现象解释:

文件描述符规则:查看自己的文件描述表,分配最小的没有使用的文件描述符;

由于我们把显示器给关掉了,那么文件描述符1就是最小的没有使用的,这样log.txt就会被分配1为文件描述符;这其实就是一个重定向操作;

看下面的图:

一开始fd_array[1]指向的是显示器,由于close(1),加上open log.txt这样fd_array[1]指向的就是log.txt;

因为重定向的本质是在内核中改变文件描述符特点下标的内容,与上层无关;

fprintf()/printf()  --->stdout  --->struct FILE --->stdout ---->_fileno ==1;

所以fprintf()/printf() 看的就是_fileno ==1;由于重定向后log.txt的fd为1 ,自然fprintf()/printf()的内容打印到log.txt中;

如果我们一直用这种手动重定向的方式,比较麻烦;可以用系统调用:dup2()

看一下代码:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<unistd.h>
  6 #include<string.h>
  7 #include<stdlib.h>
  8 const char *filename="log.txt";
  9 
 10 int main()
 11 {
 12     int fd = open(filename,O_CREAT | O_WRONLY | O_TRUNC,0666);
 13     //dup2(fd,1);
 14 
 15     printf("hello world,fd:%d\n",fd);
 16     fprintf(stdout,"hello world\n");
 17     fflush(stdout);
 18     close(fd);
 19     return 0;
 20 }

上述的代码运行结果:会直接打印到显示器上;

如果把dup2(fd,1);复原:显示器上不会显示,而是在log.txt上显示

 其实本质就是将fd覆盖1 指向下标的内容;

缓冲区

1、缓冲区是什么?

缓冲区就是一段内存空间


2、为什么要有缓冲区?

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


3、怎么办?

     a、刷新策略
               1、立即刷新  fflush(stdout)(c语言的刷新)、fsync(fd)(系统调用的刷新)
               2、行刷新  (显示器)
               3、全缓冲  (缓冲区写满,才刷新,普通文件)
     b、特殊情况
               进程退出,系统会自动刷新
               强制刷新 

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

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

相关文章

SpringBoot 集成 Ehcache 实现本地缓存

目录 1、Ehcache 简介2、Ehcache 集群方式3、工作原理3.1、缓存写入3.2、缓存查找3.3、缓存过期和驱逐3.4、缓存持久化 4、入门案例 —— Ehcache 2.x 版本4.1、单独使用 Ehcache4.1.1、引入依赖4.1.2、配置 Ehcache4.1.2.1、XML 配置方式4.1.2.1.1、新建 ehcache.xml4.1.2.1.2…

字节放大招:无需LORA训练,小红书写真轻松搞定,Pulid-Flux换脸方案来了

前言 在这之前&#xff0c;SD常用的换脸节点还不支持Flux模型&#xff0c;使用Flux 做虚拟模特最好的方法是炼制人脸lora&#xff0c;但是炼丹是个有技术门槛的活。 之前文章有提过字节跳动的 Pulid团队&#xff0c;率先推出了Pulid-Flux模型&#xff0c;但是之前只能在线上使用…

vivo/iqoo原子笔记 拍试卷去手写或者叫还原试卷。

1、如果我们经常做试卷的时候&#xff0c;发现有错的&#xff0c;想重新做一下。那就要去掉原来的手写的答案。 2、网上的App或软件多的就是&#xff0c;但大多是要收费的&#xff0c;那么我们如何利用手机里的功能&#xff0c;来基本达到这一效果呢&#xff1f; 3、手机自动…

Spring Boot实现的医院资源优化工具

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…

ASCII码、Unicode编码和UTF-8编码介绍

1.ASCII码 2.Unicode编码 3.UTF-8编码

如何训练自己的大模型,答案就在这里。

训练自己的AI大模型是一个复杂且资源密集型的任务&#xff0c;涉及多个详细步骤、数据集需求以及计算资源要求。以下是根据搜索结果提供的概述&#xff1a; 详细步骤 \1. 设定目标&#xff1a; - 首先需要明确模型的应用场景和目标&#xff0c;比如是进行分类、回归、生成文本…

实现一个计算器的功能(一般形式、函数指针数组的形式、回调函数的形式)

实现一个计算器的功能&#xff1a; 一般的形式&#xff1a; #include<stdio.h> int Add(int x, int y) {return x y; } int Sub(int x, int y) {return x - y; } int Mul(int x, int y) {return x * y; } int Div(int x, int y) {return x / y; } void menu() {printf…

【Linux】Linux命令与操作详解(一)文件管理(文件命令)、用户与用户组管理(创建、删除用户/组)

文章目录 一、前言1.1、Linux的文件结构是一颗从 根目录/ 开始的一个多叉树。1.2、绝对路径与相对路径1.3、命令的本质是可执行文件。1.4、家目录 二、文件管理2.1、文件操作1、pwd2、ls3、cd4、touch5、mkdir6、cp7、rm8、mv9、rmdir 2.2、查看文件1、cat2、more3、less4、hea…

6.1K Star,简简单单的看直播

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub 指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 导语 在视频内容飞速发展的时代&#xff0c;实时推流和流媒体技术成…

java并发之并发实践

一、死锁 线程死锁 死锁是指两个或者两个以上的线程在执行的过程中&#xff0c;因争夺资源产生的一种互相等待现象。 假设线程 A 持有资源 1&#xff0c;线程 B 持有资源 2&#xff0c;它们同时都想申请对方的资源&#xff0c;那么这两个线程就会互相等待而进入死锁状态。 使用…

多功能声学综合馆:流动会场的新标杆—轻空间

随着现代会议、展览、演出和活动的多元化需求&#xff0c;场地的灵活性与适应性变得尤为重要。传统的固定场馆难以满足各类活动的复杂需求&#xff0c;而多功能声学综合馆凭借其灵活、便捷、专业的声学性能&#xff0c;成为了市场上一颗闪耀的新星。其“流动会场”的特性&#…

计算机取证

文章目录 思维导图计算机取证数据固定FTK ImageDumpIt 数据分析——磁盘镜像仿真软件自动仿真手动仿真仿真后的取证分析 基本信息及用户痕迹1.名称、版本、build号、系统目录、位数、产品秘钥等2.安装时间3.最后一次关机时间4.USB使用记录5.WIFI信息6.近期访问过的文档、程序7.…

动销方案:剑指市场份额扩张

在竞争激烈的市场中&#xff0c;企业如何扩大市场份额&#xff1f;动销&#xff0c;即拉动销售&#xff0c;乃是关键手段。 首先进行市场分析。行业现状方面&#xff0c;以快速消费品行业为例&#xff0c;市场规模大且持续增长&#xff0c;但竞争激烈&#xff0c;各大品牌不断推…

深化理解:RAG应用搭建进阶指南

大型语言模型&#xff08;LLM&#xff09;的文本推理能力&#xff0c;宛如一位博学的公民&#xff0c;其智慧之源来自于互联网上公开的文献宝库。想象一下&#xff0c;这位名为LLM的公民&#xff0c;如同一位勤奋的学者&#xff0c;借阅了图书馆中所有的书籍&#xff0c;并将这…

杀疯了深度解析chatGPT和NLP底层技术——复旦大学新版《自然语言处理导论》

在今年的2月28号&#xff0c;复旦张琦教授放出了自己的大招&#xff0c;发布了自己历时近三年之久&#xff0c;即自身对自然语言处理20年研究的著作 全文共 600页&#xff0c; 涉及了 787 篇参考文献&#xff0c; 全面且深度的解析了与NLP的底层知识。 内容介绍&#xff1a; …

【C++ Primer Plus】4

2 字符串 字符串是存储在内存的连续字节中的一系列字符&#xff1b;C处理字符串的方式有两种&#xff0c; c-风格字符串&#xff08;C-Style string&#xff09;string 类 2.1 c-风格字符串&#xff08;C-Style string&#xff09; 2.1.1 char数组存储字符串&#xff08;c-…

网 络 安 全

网络安全是指保护网络系统及其所存储或传输的数据免遭未经授权访问、使用、揭露、破坏、修改或破坏的实践和技术措施。网络安全涉及多个方面&#xff0c;包括但不限于以下几个方面&#xff1a; 1. 数据保护&#xff1a;确保数据在传输和存储过程中的完整性和保密性&#xff0c;…

微服务es+Kibana解析部署使用全流程

1、介绍 ElasticSearch是Java开发的一款开源的&#xff0c;分布式的搜索引擎。 它的搜索采用内存中检索的方式&#xff0c;大大提高了检索的效率&#xff0c;es是基于REST API的方式对数据操作的&#xff0c;可以让存储、检索、索引效率更高。 1、es可以做什么 网站检索数据…

python爬虫 - 深入requests模块

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 ​编辑 前言 一、下载网络文件 &#xff08;一&#xff09;基本步骤 &#xff0…

【AIGC】如何选择AI绘画工具?Midjourney VS Stable Diffusion

前言 文章目录 &#x1f4af;如何选择合适的AI绘画工具 个人需求选择比较工具特点社区和资源 &#x1f4af; Midjourney VS Stable Diffusion&#xff1a;深度对比与剖析 使用费用对比使用便捷性与系统兼容性对比开源与闭源对比图片质量对比上手难易对比学习资源对比作品版权问…