【linux】重定向|缓冲区

news2024/11/20 15:26:11

read函数

在这里插入图片描述

将文件标识符为fd的文件内容读到buf中去,读count个,read的返回值是实际读到的个数,有可能文件中没有count个,但是read返回的还是实际读到的个数

stat函数

在这里插入图片描述

调用这个函数可以查到对应文件的属性,比方说文件大小
pathname:用于指定一个需要查看属性的文件路径。
buf:struct stat 类型指针,用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 struct stat 变量的指针,获取到的文件属性信息就记录在 struct stat 结构体中。
返回值:成功返回 0;失败返回-1,并设置 error。

  1 #include<stdio.h>
  2 #include <unistd.h>
  3 #include <sys/types.h>
  4 #include <sys/stat.h>
  5 #include <fcntl.h>
  6 #include<stdlib.h>
  7 const char* filename="log.txt";
  8 int main()
  9 {
 10 struct stat st;
 11 int n=stat(filename,&st);
 12 if(n<0) return 1;
 13 printf("file size:%lu\n",st.st_size);
 14 int fd=open(filename,O_RDONLY);
 15 if(fd<0)
 16 {
 17 perror("open");
 18 return 2;
 19 }
 20 printf("fd:%d\n",fd);
 21 char* file_buffer=(char*)malloc(st.st_size);                                                                       
 22 n=read(fd,file_buffer,st.st_size);
 23 if(n>0)
 24 {
 25 
 26 file_buffer[n]='\0';
 27 }
 27 printf("%s",file_buffer); 
 28 free(file_buffer);
 29 close(fd);
 30 return 0;
 31 }
 32 

 

代码解释:stat函数获取filename(log.txt)的文件属性,然后就可以直接获取文件大小在结构体变量中st.st_size,打印文件的文件标识符fd,malloc一个和文件大小一样的file_buffer模拟缓冲区,通过read函数将文件内容读到file_buffer中。read读取实际读到的大小,返回为实际大小n,并在模拟的缓冲区的最后加’\0’,释放file_buffer空间,关闭文件.
在这里插入图片描述

如果要查看文件对应的属性结构体在/usr/include/libio.h
在这里插入图片描述


重定向

    1 #include<stdio.h>
    2 #include <sys/types.h>
    3 #include <sys/stat.h>
    4 #include <fcntl.h>
    5 #include <unistd.h>
    6 int main()
    7 {
    8 close(1);
    9 
   10 int fd=open("log.txt",O_CREAT|O_TRUNC|O_WRONLY,0666);
   11 if(fd<0)
   12 {
   13 perror("open fail");
   14 }
   15 const char* buf="hello world";
   16 write(1,buf,sizeof(buf));                                                                                        
   17 printf("log.txt:fd:%d",fd);   
   18 } 

代码解释:我们关闭文件标识符为1的屏幕,根据文件描述符的分配规则:查自己的文件描述表,分配最小的没有被使用过的fd,于是新创建的文件的文件描述符被分配1,以至于本来要显示在屏幕上的东西,显示在了文件log.txt中,这就叫做重定向
在这里插入图片描述

在这里插入图片描述


使用重定向并非要关闭一个文件描述符对应的文件,让另一个来替代这个被关闭的文件,我们可以使用dup2函数也能实现重定向
在这里插入图片描述

dup2函数原理说明:
在这里插入图片描述

在这里插入图片描述
重定向的本质:是在内核中改变文件描述符特定下标的内容,和上层无关,文件描述符下标对应内容的拷贝

使用dup2实现的重定向和close(1)重新分配一样的效果

  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 int main()
  7 {
  8 
  9 
 10 int fd=open("log.txt",O_CREAT|O_TRUNC|O_WRONLY,0666);
 11 if(fd<0)                                                                                                           
 12 {
 13 perror("open fail");
 14 }
 15 dup2(fd,1);
 16 const char* buf="hello world";
 17 write(1,buf,sizeof(buf));
 18 printf("log.txt:fd:%d",fd);
 19 }

在这里插入图片描述

在这里插入图片描述


缓冲区

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

代码解释:我们关闭屏幕,让本来打印到屏幕上去的,打印到文件log.txt中去.

在这里插入图片描述

在这里插入图片描述
我们发现没有打印到文件中去

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

当我加上一个fflush后,就出现了,到底是为什么呢???

在这里插入图片描述

在这里插入图片描述


这里就要提出缓冲区这个概念了,实际上存在一个语言级别的缓冲区,当我们使用printf,fprintf的时候,我们是将对应内容写到了语言级别的缓冲区里面,并没有写到操作系统对应内核的操作系统里面,如果此时不加fflush的话,就关闭文件,对应文件的内核缓冲区中没有数据,而文件中写入的数据,都是文件对应的内核缓冲区中冲刷过来的.这里fflush的作用是将语言级别的缓冲区的内容冲刷到对应文件的内核缓冲区中去

画一个图理解一下
在这里插入图片描述

在这里插入图片描述


缓冲区知识总结:缓冲区包括用户级缓冲区(语言层面的)和内核级缓冲区,主要作用是解耦和提高效率,提高了使用者的效率,使用者只需将printf将内容放到用户级缓冲区中,剩下的的事情操作系统帮你干,提高了刷新IO的效率
缓冲区是什么?
一段内存空间
为什么要存在缓冲区?
给上层提供高效的IO体验,间接提供整体效率
刷新策略
1.立即刷新
2.行刷新(方便用户阅读习惯)
3.全缓冲:缓冲区写满,才刷新(普通文件采用这个)
特殊情况:
进程退出,系统会自动刷新(强制)


 1 #include<stdio.h>
  2 #include <unistd.h>
  3 int  main()
  4 {
  5 fprintf(stdout,"hello fprintf\n");
  6 printf("hello printf\n");
  7 const char* buf="hello write\n";
  8 write(1,buf,sizeof(buf));                                                                                          
  9 return 0;
 10 
 11 
 12 }



  1 #include<stdio.h>
  2 #include <unistd.h>
  3 #include<string.h>
  4 int  main()
  5 {                                                                                                                  
  6 fprintf(stdout,"hello fprintf\n");
  7 printf("hello printf\n");
  8 const char* buf="hello write\n";
  9 write(1,buf,strlen(buf));
 10 fork();
 11 return 0;
 12 
 13 
 14 }

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


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

我们如果往文件中输出的话,为什么会存在下面的问题呢
在这里插入图片描述
解释:如果是输出到屏幕上的,属于行刷新,一行满了就立刻刷新到内核级缓冲区中去,而如果输出到文件中去,他是全缓冲,直到用户级缓冲区写满之后,才会写入到内核级缓冲区中去,而write是直接写到内核级缓冲区里面的,在fork之前,语言级缓冲区里面只有父进程缓冲区的内容也就是只有一遍hello fprintf ,hello printf,当fork后,由于子进程是复制父进程好多的内容,包括pcb结构,也就是说子进程的文件缓冲区和父进程的文件缓冲区指向的是同一个,如果发生写时拷贝的话,操作系统会给子进程单独搞一个内核级缓冲区,内容和父进程一样hello fprintf ,hello printf,深拷贝导致缓冲区地址不一样,但是都是一个文件的缓冲区,子进程写时拷贝后导致这个文件的文件缓冲区满了,然后就会刷新,将父进程的缓冲区,和子进程的缓冲区的内容都刷新到文件中去,write是系统调用,自然不会有语言级的缓冲区,也不会让子进程在拷贝一个新的缓冲区


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

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

相关文章

BUUCTF-MD5

BUUCTF-MD5 1 注意&#xff1a;得到的 flag 请包上 flag{} 提交 27120bd8-e273-4528-97a9-28dcebe236de.zip flag{admin1} e00cf25ad42683b3df678c61f42c6bdahttps://www.cmd5.com/

3.6k star, 免费开源跨平台的数据库管理工具 dbgate

3.6k star, 免费开源跨平台的数据库管理工具 dbgate 分类 开源分享 项目名: dbgate -- 免费开源跨平台的数据库管理工具 Github 开源地址&#xff1a; GitHub - dbgate/dbgate: Database manager for MySQL, PostgreSQL, SQL Server, MongoDB, SQLite and others. Runs under…

《UE5_C++多人TPS完整教程》学习笔记30 ——《P31 摄像机和弹簧臂(Camera And Spring Arm)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P31 摄像机和弹簧臂&#xff08;Camera And Spring Arm&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;…

在云端遇见雨云:一位服务器寻觅者的指南

引言&#xff1a;寻觅一座云端归宿 当我踏入数字世界的边缘&#xff0c;带着对网络的探索与期待&#xff0c;我迫切需要一座安全可靠的数字栖息地。云计算技术正如一场魔法般的变革&#xff0c;而在这片广袤的云端中&#xff0c;雨云就像是一位友善的向导&#xff0c;引领我穿越…

【AAOS车载系统+AOSP14系统攻城狮入门实战课】:正式上线了(二百零三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

代码随想录算法训练营第三十天| 332.重新安排行程, 51. N皇后, 37. 解数独,总结

题目与题解 参考资料&#xff1a;回溯总结 332.重新安排行程 题目链接&#xff1a;332.重新安排行程 代码随想录题解&#xff1a;332.重新安排行程 视频讲解&#xff1a;带你学透回溯算法&#xff08;理论篇&#xff09;| 回溯法精讲&#xff01;_哔哩哔哩_bilibili 解题思路&a…

c语言--动态内存管理(malloc、realloc、free、calloc)

目录 一、为什么要有动态内存分配二、 malloc和free2.1 malloc 三、 calloc和realloc3.1calloc3.2 realloc 四、常见的动态内存的错误4.1 对NULL指针的解引用操作4.2 对动态开辟空间的越界访问4.3 对非动态开辟内存使用free释放4.4 使用free释放⼀块动态开辟内存的一部分4.5对同…

Midjourney艺术家分享|By Moebius

Moebius&#xff0c;本名让吉拉德&#xff08;Jean Giraud&#xff09;&#xff0c;是一位极具影响力的法国漫画家和插画师&#xff0c;以其独特的科幻和幻想风格而闻名于世。他的艺术作品不仅在漫画领域内受到高度评价&#xff0c;也为电影、时尚和广告等多个领域提供了灵感。…

逆向案例十三(1)——贝壳网登录密码逆向

链接地址&#xff1a;合肥房产网_合肥二手房|租房|新房|房地产信息网【合肥贝壳找房】 点击登录&#xff0c;打开开发者工具&#xff0c;点击账号密码登录&#xff0c;输入错误密码和账号 。找到登录的数据包。打开发现有许多参数加密。数据包是authenticate 再登陆一次看哪些…

分类预测 | Matlab实现CPO-LSSVM冠豪猪算法优化最小支持向量机数据分类预测

分类预测 | Matlab实现CPO-LSSVM冠豪猪算法优化最小支持向量机数据分类预测 目录 分类预测 | Matlab实现CPO-LSSVM冠豪猪算法优化最小支持向量机数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现CPO-LSSVM冠豪猪算法优化最小支持向量机数据分类预…

机器学习模型:决策树笔记

第一章&#xff1a;决策树原理 1-决策树算法概述_哔哩哔哩_bilibili 根节点的选择应该用哪个特征&#xff1f;接下来选什么&#xff1f;如何切分&#xff1f; 决策树判断顺序比较重要。可以使用信息增益、信息增益率、 在划分数据集前后信息发生的变化称为信息增益&#xff0c…

MySQL故障排查与优化

一、MySQL故障排查 1.1 故障现象与解决方法 1.1.1 故障1 1.1.2 故障2 1.1.3 故障3 1.1.4 故障4 1.1.5 故障5 1.1.6 故障6 1.1.7 故障7​ 1.1.8 故障8 1.1.9 MySQL 主从故障排查 二、MySQL优化 2.1 硬件方面 2.2 查询优化 一、MySQL故障排查 1.1 故障现象与解决方…

Windows Docker 部署 Firefly III 开源记账软件

一、简介 Firefly III是一款开源的记账软件&#xff0c;支持全球多种语言。它可以帮助用户追踪和管理个人账目、预算和账单&#xff0c;减少支出&#xff0c;节省更多。该软件支持多种货币、银行账户和投资账户&#xff0c;并提供了丰富的报表功能&#xff0c;帮助用户更好地了…

Netty客户端发送数据给服务器的两个通道(1)

EventLoopGroup group new NioEventLoopGroup();// 设置的连接group。 Bootstrap bootstrap new Bootstrap().group(group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) // 超时时间。 .channel(NioSocketChannel.class).handler(new ChannelInitializer() { Ov…

JVM专题——类文件加载

本文部分内容节选自Java Guide和《深入理解Java虚拟机》, Java Guide地址: https://javaguide.cn/java/jvm/class-loading-process.html &#x1f680; 基础&#xff08;上&#xff09; → &#x1f680; 基础&#xff08;中&#xff09; → &#x1f680;基础&#xff08;下&a…

Makefile:make install的实现(十一)

1、make install的概念 在Linux环境下有些时候软件或者服务会通过源码安装&#xff0c;执行一些make、make install、make clean的指令。例如&#xff1a;redis make&#xff1a;编译所有的文件、生成一些动态库、静态库、可执行程序等等make install&#xff1a;通常会创建一个…

Qt | Qt 框架结构概述

一、Qt 基本框架概述 1、Qt 5 引入了模块化的概念,Qt 5 将实现众多功能的 Qt 库细分为各个模块,也就是说一个模块中包含了实现某种功能的众多 C++类库,比如 Qt GUI 模块用于图形用户界面绘制,该模块中包含了实现 GUI 组件的类库,比如 QFont、QImage、QOpenGL、QWindow 等…

11.python的字典dict(下) 遍历字典,结构优化

11.python的字典dict(下) 遍历所有的键值对 items()方法是字典的一个内置方法&#xff0c;用于返回字典中所有键值对的视图&#xff08;view&#xff09;。它返回一个可迭代的对象&#xff0c;每个元素都是一个包含键和对应值的元组。 下面用一个例子来说明items()方法的用法…

闻风丧胆的算法(二)

&#x1f308;个人主页&#xff1a;Rookie Maker &#x1f525; 系列专栏&#xff1a;算法 &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于IT的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x1f601; 喜欢的小…

第十二届通信和宽带网络国际会议(ICCBN 2024)即将召开!

2024年第十二届通信和宽带网络国际会议将于2024年7月25日至27日在西藏林芝举行会议涵盖的议题广泛多样&#xff0c;包括但不限于&#xff1a;5G、6G技术与应用&#xff0c;宽带网络架构和优化&#xff0c;物联网与智能连接&#xff0c;人工智能在通信领域的应用&#xff0c;数据…