[Linux]基础IO(中)---理解重定向与系统调用dup2的使用、缓冲区的意义

news/2024/12/5 2:13:47/

重定向理解

        在Linux下,当打开一个文件时,进程会遍历文件描述符表,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。

代码验证:

①:先关闭下标为0的文件,在打开一个文件,此时该文件的fd为0

  #include<stdio.h>#include<sys/types.h>#include<fcntl.h>#include<string.h>#include<unistd.h>int main(){//提前关闭下标为0的文件close(0);int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);if(fd<0){perror("open");return 1;}printf("log.txt打开成功:fd:%d\n",fd);                                                                                                                                                       close(fd);return 0;}

②:关闭下标为1的文件,在打开一个新的文件,再用 printf 打印一段信息

  #include<stdio.h>#include<sys/types.h>#include<fcntl.h>#include<string.h>#include<unistd.h>int main(){//提前关闭下标为1的文件close(1);int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);if(fd<0){perror("open");return 1;}printf("log.txt打开成功:fd:%d\n",fd);fflush(stdout);                                                                                                                                                       close(fd);return 0;}

出现的问题:

1.printf输出的内容没有出现在显示器上

2.应该在显示器上出现的信息却被加载到了文件中

【解释】:

在上述代码中,我们先关闭了下标为1的文件,在操作系统中该文件对应的是标准输出(显示器),而我们打开文件后,会将下标1作为该文件的描述符,printf函数的作用就是向下标为1的文件中写入信息,但是此时下标1对应的不在是标准输出了,对应的是我们打开的文件,但是上层仍认为1号下标对应的就是显示器,所以向1号下标文件写入就相当于向文件写入,而这个现象就称之为重定向,其本质是在内核中改变文件描述符表特定下标的内容,与上层无关

系统调用函数 dup2

该函数的功能是将文件描述符oldfd所对应文件内容拷贝给newfd对应文件

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

举例:

  #include<stdio.h>#include<sys/types.h>#include<fcntl.h>#include<string.h>#include<unistd.h>int main(){int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);if(fd<0){perror("open");return 1;}dup2(fd,1);printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");                                                                                                                                                                   fflush(stdout);close(fd);return 0;}

缓冲区理解

如果将上述代码中的 fflush(stdout) 删除的话,应该向文件写入的信息又写不进去了,这又是为什么呢?程序结束不是会自动刷新缓冲区吗?信息去哪里了?

【解释】:

在c语言中,为了用户使用方便,封装了三个结构体,stdout、stdin、stderr,这三个结构体中除了封装了文件描述符外,还存在着语言级别的文件缓冲区

在[Linux]基础IO(上)--理解文件系统调用、文件描述符、万物皆文件一文中我们谈到,每一个文件的struct file都存在一个内核级的文件缓冲区,printf输出的内容会先保存在语言级别的那个缓冲区中,C语言在通过文件描述符将该缓冲区的内容加载到内核级别的文件缓冲区中,操作系统在刷新到外设

此时,程序中printf输出的内容就保存在语言级别的文件缓冲区中,虽然程序结束时会自动刷新缓冲区,但是在程序结束前,我们就已经将文件关闭了,就无法向文件中写入信息了,当程序结束时,这部分数据就丢失了

缓冲区刷新策略

1.立即刷新:fflush(stdout)  int fsync(int fd) 

2.行刷新:写满一行就刷新(显示屏)

3.全刷新:当缓冲区写满才刷新

4.特殊情况:程序结束强制刷新

缓冲区的意义:
  •  解耦:对于语言级别的文件缓冲区,只需要想怎样将数据导入缓冲中,不需要管语言怎么再将数据导入内核级文件缓冲区,对于内核级文件缓冲区,将数据导入进来后,就不需要管操作系统怎样将数据刷新到外设中了
  • 提高效率:系统调用是有一定的成本的,当缓冲区写满或者写完一行时,再调用系统接口,一次或多次的将内容进行处理,这样可以极大减少系统调用的次数,不仅可以提高IO速率,也可以提高用户的使用效率

http://www.ppmy.cn/news/1404977.html

相关文章

合并两个单链表

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 但行前路&#xff0c;不负韶华&#…

探析Drools规则引擎的工作机制

目录 一、工作原理 二、工作流程 2.1 初始化环境 2.2 添加规则文件 2.3 编译规则文件 2.4 插入到工作内存 2.5 规则匹配与激活 2.6 规则执行 三、Drools 其他特性 3.1 符合事实 3.2 决策表 3.3 规则生命周期管理 3.4 规则流 四、Rete 算法 一、工作原理 Drools 规则引擎的工…

谷歌(Google)技术面试——在线评估问题(一)

谷歌&#xff08;Google&#xff09;面试过程的第一步&#xff0c;你可能会收到一个在线评估链接。 评估有效期为 7 天&#xff0c;包含两个编码问题&#xff0c;需要在一小时内完成。 以下是一些供你练习的在线评估问题。 在本章结尾处&#xff0c;还提供了有关 Google 面试不…

最新AI工具系统ChatGPT网站运营源码SparkAi系统V6.0版本,GPTs应用、AI绘画、AI换脸、垫图混图、Suno-v3-AI音乐生成大模型全支持

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

酷开科技智慧AI让酷开系统大显身手!

时代的浪潮汹涌而至&#xff0c;人工智能作为技术革新和产业变革的重要引擎&#xff0c;正深刻地影响着各行各业。在科技的海洋中&#xff0c;AI技术正逐渐渗透到我们的日常生活中&#xff0c;为我们带来前所未有的便捷和智慧。酷开科技用技术探索智慧AI&#xff0c;别看它只是…

微服务(基础篇-007-RabbitMQ部署指南)

目录 05-RabbitMQ快速入门--介绍和安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p65&vd_source60a35a11f813c6dff0b76089e5e138cc 1.单机部署 1.1.下载镜像 1.2.安装MQ 2.集群部署 2.1.集群分类 2.2.设置网络 视频地址&#xff1a; 05-Rab…

达梦数据库用户与权限管理

达梦数据库用户与权限管理 用户管理口令策略管理用户资源限制 权限管理一般权限特殊权限 角色管理 用户管理 达梦数据库安装后创建的内置用户&#xff1a; SYS&#xff1a;内置用户&#xff0c;不允许登录。该用户下有常用的数据字典&#xff1b;SYSDBA&#xff1a;系统管理员…

Linux(05) Debian 系统修改主机名

查看主机名 方法1&#xff1a;hostname hostname 方法2&#xff1a;cat etc/hostname cat /etc/hostname 如果在创建Linux系统的时候忘记修改主机名&#xff0c;可以采用以下的方式来修改主机名称。 修改主机名 注意&#xff0c;在linux中下划线“_”可能是无效的字符&…