【Linux】进程控制(文件操作符收尾+重定向)

上一回进程与文件系统我们主要看了很多文件描述符的知识

1.如何理解一切皆文件?

 

每个设备被打开时,OS给每个文件创建一个自己的struct file 里面填充自己的属性以及自己的缓冲区,其中还有函数指针,里面保存函数地址,通过这个地址可以找到对应外设的read/write方法

 

所以结合上节课的内容我们再来梳理一下进程是如何打开文件的

首先进程要通过自己PCB中内置的struct files_struct*files指针找到struct files_struct 然后在这个结构体内部找到数组struct file* fd_array[ ]这个进而找到OS为这个进程分配的fd(数组下标),通过下标fd找到数组中对应的内容(file*),通过file*指针找到内存中保存struct file的数据结构,访问这个数据结构,找到那个进程要找的struct file!!!!

 如果这个struct file是键盘文件,那么结构体中会有函数指针,指向键盘的读写方法

 这就是使用C语言来设计面向对象 

我们使用OS的本质:通过进程的方式进行OS的访问

来看操作系统层面:首先明确必须访问fd才能找到文件,任何语言访问外设或文件都必须经历OS

之前我们说fopen的返回值是FILE* 这里的FILE其实是一个结构体,那他和我们上面说的struct file有关系吗? 没有,只是上下层的关系

这个结构体是C语言提供的

所以平常我们在安装VS2019的时候是在安装什么?

安装语言对应的头文件和库

这个FILE结构体一定封装了fd!!!!!但是怎么验证?

 

这个_fileno就是每个文件的fd


 2.重定向

重定向有三种:

  • 输出重定向 >

 刚才程序运行的结果是0 1 2 ,我们输出重定向到log里面

  • 输入重定向 <

指定文件作为命令的输入设备

 此时log是输入设备

相当于直接cat log.txt

  • 追加重定向 >>

输出重定向会清空数据,要是不想被清空就使用追加重定向

 

 但是这样的理解太过肤浅,我们深入理解一下重定向的本质

上回我们说过,fd的分配是从下标0开始,遇到第一个没被占用的

看一下这样的代码

1.输出重定向的理解

 

 本该打印到显示器上的东西全都到log.txt中

因为printf只认1,根本不考虑哪个文件fd=1

所以重定向的原理:在上层无法感知的情况下,在OS内部更改进程fd

上面的操作相当于 1>log.txt

也就是log.txt占用了fd=1

2.输入重定向的理解

  

 和刚才其实是一样的scanf函数只认0,他是从0获取数据写到 a b中

所以你关闭了0文件,log.txt分配的fd就是0

自然会从log.txt中拿数据

3.追加重定向的理解

此时open的选项把O_TRUNC改成O_APPEND


现在我想让你把写到stdout的内容打印到log.txt,把写入stderr的内容打印到err.txt怎么搞?

 

 OK,理解一下这条指令

首先运行a.out 把log.txt的fd分配成1,把err.txt的fd分配成2,此时printf只认1,所以hello stdout写入到log.txt fprintf只认2,所以把格式化之后的字符串写入到err.txt中

那如果现在我想把两个字符串都打印到显示器上

 首先运行a.out 然后把运行结果(此时应该只有hello stdout)放到log.txt,hello stderr在2文件里,然后把2也写入到显示器文件,这样就可以一起输出啦

其中1>&2是把1重定向成2的地址,也就是用2的地址的fd=1

如果你想把两个字符串汇总到一起写入log.txt

这是把2重定向成1的地址然后./a.out的时候一起把1 的内容重定向到log.txt 


 但是如果每次重定向都要关闭一个再打开一个文件也太挫了

有没有更好的方法?当然

只要看dup2就行,dup想看懂太简单了

 那么请你回答  1 > 一个文件(他的文件描述符为fd)

此时应该如何传参,是fup(1,fd)还是反过来?

应该是dup2(fd,1),这地方确实是有点绕,但是我的理解是:之前我们不是说过要把文件的fd分配成1,所以fd应该是1的一份拷贝


3.缓冲区 

之前我们总是说缓冲区缓冲区,缓冲区到底在哪? 

 

 又看到这个现象完全懵了

现在我们好好解释一下

那么C库的刷新策略有哪些?

1.无缓冲 (直接写给OS,而不是先放C库的缓冲区) 

2.行缓冲(碰到'\n'就刷)

3.全缓冲(缓冲区写满再刷新)

值得注意的是:

显示器采用行缓冲,普通文件采用全缓冲

为什么要有缓冲区?节省调用者的时间,因为系统调用也是花费时间的

缓冲区在哪?在fopen打开文件的时候,会得到FILE结构体,缓冲区就在其中

所以我们来解释上面的问题

首先C库函数会把第一个字符串放在自己的缓冲区,因为是写入到显示器文件采取行刷新,正好字符串末尾有\n直接刷新,即写给操作系统的stdout文件的缓冲区

write是系统调用,直接可以把hello write写到stdout的缓冲区

所以直接在fork之前就完成刷新了,根本没有创建子进程的事情,也就是有没有fork结果都是一样的

在进程退出之前,OS根据自己的刷新策略把stdout缓冲区的内容调用显示器的写方法,把内容显示到屏幕上

(如果没有fork)

 


再来看一下有fork重定向之后的结果是为什么? 

重定向之后 write还是直接写到系统的缓冲区,但是重定向到普通文件,所以C库的刷新策略变成了全缓冲,所以在执行完write语句之后应该是这样的

这部分的数据属于父进程的,是父进程创建的 

然后fork起作用了,父子进程在退出的时候都要刷新,谁先刷新谁先进行写时拷贝,所以hello fprintf字符串被写入了两次(写入stdout的缓冲区)


其实到这里我们的理解还不是特别深刻,自己写一个缓冲区就好了

 

需要用到一个函数,fsync函数,将文件数据同步到硬盘 

 

 

 main.c

  1 #include "mystdio.h"
  2 #include <string.h>
  3 
  4 #define LOG "log.txt"
  5 int main()
  6 {
  7   MY_FILE*fp=my_fopen(LOG,"w");
  8   const char * msg="hello myfwrite";
  9 int cnt=5;
 10 while(cnt)
 11 {
 12 char buf[1024];
 13 snprintf(buf,sizeof(buf),"%s,%d",msg,cnt--);
 14 size_t num=myfwrite(buf,strlen(buf),1,fp);
 15 printf("当前成功写入: %lu个字节\n", num);                                                                             
 16 my_fflush(fp);
 17 }
 18   return 0;
 19 }

mystdio.h

  1 #pragma once
  2 #include <stdio.h>
  3 #define NUM 1024
  4 typedef struct _MY_FILE
  5 {
  6 int fd;
  7 int current;
  8 int flag;
  9 char outputbuffer[NUM];
 10 }MY_FILE;
 11 
 12 MY_FILE* my_fopen(const char *pathname,const char *mode );
 13 size_t myfwrite(const void *ptr,size_t size,size_t nmemb,MY_FILE *stream);
 14 int my_fflush(MY_FILE*fp);                                                                                            
 15 int my_close(MY_FILE*fp);

mystdio.c

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

股票量价关系基础知识3

成交量变化的表现形式 成交量变化的表现形式主要有以下几种 一、缩量 一般界定当日成交量低于前一交易日成交量10%以上为缩量。 缩量往往发生在上升途中的回调末期、上涨末期以及股价下跌的中后期。一般下跌趋势中的缩量阶段&#xff0c;往往意味着股价仍未见底&#xff0c;不能…

DOM事件模型与事件委托

事件 JS与HTML之间的交互通过事件实现。 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。 可以使用监听器来预定事件&#xff0c;以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察者模式 事件流 事件流描述的是从页面中接受事件的顺序 事件冒泡 微软…

程序员的下一个风口

面对近一年的裁员潮&#xff0c;以及 GPT 出现带来的 AI 颠覆潮流&#xff0c;各种话题出现&#xff1a;「前端已死」、「后端已死」、「Copy/Paste 程序员将被 AI 取代」。程序员行业是否还有发展空间&#xff1f; 这一两年的就业机会是因为经济衰落周期内造成的&#xff0c;不…

MATLAB 常用数学函数和数组和字符串、元胞数组和结构体,MATLAB 编程,关系运算符和逻辑变量

目录 MATLAB 零基础学习 简介 使用平台 一、MATLAB 界面 二、基础操作 使用方法 常用数学函数 初等函数 三角函数 指数和对数 复数 标点符号 常用操作 三、文件类型 数组 一、数组基础知识 二、数组创建与操作 创建 数组操作 字符串数组 字符串、元胞数组…

移动互联网市场是不需要Android 开发了吗?

就近有不少朋友在吐槽&#xff1a;如今Android工作真的难找&#xff01;从年初找到了现在&#xff0c;是市场不需要Android 开发人才了&#xff0c;人都迷茫了&#xff0c;是不是应该考虑转行了&#xff1f; 其实这种情况往年也是有的&#xff0c;但是今年显得的更严重一些。我…

在数据化知识经济的时代,你该学会如何经营好自己的知识管理

在当今的数据化知识经济时代&#xff0c;知识管理已经越来越成为了一个必备的技能。在这个竞争激烈的时代&#xff0c;拥有良好的知识管理能力&#xff0c;可以帮助我们更好地应对各种挑战和机遇。 如何经营好自己的知识管理 一、认识知识管理的重要性 知识管理是指通过系统…

回溯法--N皇后问题

N皇后问题 一、问题描述二、示例2.1 四皇后的2个可行解2.2 过程图示 三、问题分析3.1涉及到的概念递归回溯 3.2 分析 四、 代码实现4.1 实现思路宏观&#xff1a;微观&#xff1a; 4.2 递归函数NS图4.3 代码 一、问题描述 1、按照国际象棋的规则&#xff0c;皇后可以攻击与之处…

腾讯面试经验,岗位是C++后端

分享一篇腾讯面经&#xff0c;岗位是C后端&#xff0c;考察的内容是C、Redis、网络。 c shared_ptr的原理 答&#xff1a;内部的共享数据和引用计数实现 补充&#xff1a; shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数&#xff0c;每一个shared_ptr的拷贝都…

OpenResty(Nginx)示例

Nginx Nginx概念&#xff1a; 聊到Nginx,先简单讲一下Nginx的基本概念 Nginx是一个高性能的、开源的 Web 服务器和反向代理服务器软件&#xff0c;由 Igor Sysoev 开发。它可以作为 HTTP 服务器使用&#xff0c;也可以作为负载均衡器、HTTP 缓存、反向代理和邮件代理等其他功…

公有云云硬盘(EBS)有效范围内扩容/存储规格变更指导手册

一、背景 某公有云环境中,云主机直连的云硬盘存储某数据库数据,随着数据的积累,大约10亿多条数据,云硬盘急需扩容,但前期规划云硬盘未开启lvm卷,且当前存储容量未达EBS容量限制,最大可达32T,因此决定采用EBS规格变更的方式来实现主机存储的扩容; 二、注意点: 1)过…

WebGIS支持国内各地方坐标系数据展示的方案

在我们的实际项目开发过程中,会存在着很多的客户提供的数据是地方坐标系的数据,这些数据通常是一些类似于地块数据,点位数据等等的矢量数据。如何加载这些数据可能会让大家有些头疼。我们这篇文章来给大家提供几种解决方案。 首先要清楚一个基础的地理学知识,那就是地理坐…

5年测试被裁,去面试差点被问哭了······

我的个人背景非常简单&#xff0c;也可以说丝毫没有亮点。 学历普通&#xff0c;计算机专业二本毕业&#xff0c;毕业后出来就一直在一家小公司&#xff0c;岁月如梭细&#xff0c;算了下至今从事软件测试已经5年了&#xff0c;也点点点了五年&#xff0c;每天都是重复的工作&…

WiFi(Wireless Fidelity)基础(十)

目录 一、基本介绍&#xff08;Introduction&#xff09; 二、进化发展&#xff08;Evolution&#xff09; 三、PHY帧&#xff08;&#xff08;PHY Frame &#xff09; 四、MAC帧&#xff08;MAC Frame &#xff09; 五、协议&#xff08;Protocol&#xff09; 六、安全&#x…

【AUTOSAR】【以太网】TCPIP

目录 一、概述 二、约束和假设 三、依赖模块 3.1 EthIf 3.2 EthSM 3.3 SoAd 3.4 KeyM 3.5 CSM 四、功能说明 4.1 系统扩展性 4.2 IPv4 4.2.1 IPv4 4.2.2 ARP 4.2.3 Auto-IP 4.2.4 ICMP 4.3 IPv6 4.4 IPSec 4.5 基于IP的协议 4.5.1 本地地址表 4.5.2 UDP 4…

渗透测试--2.漏洞探测和利用

目录 一.漏洞分类 二.漏洞探测 三.漏洞利用 四.漏洞扫描 1.Nessus 2.Web应用漏洞扫描器——DVWA 五.Metasploit漏洞利用 一.漏洞分类 网络漏洞 系统漏洞 应用漏洞 人为不当配置 二.漏洞探测 渗透测试是一种测试网络、应用程序和系统安全性的方法&#xff0c;旨在发现…

phpstorm 配置xdebug

目录 配置全局环境 phpstorm 项目xdebug配置 额外补充&#xff1a; 配置全局环境 本地运行命令 php -v, 看是否有Xdebug相关的信息若没有&#xff0c;安装xdebug&#xff0c;以下是mac相关方式&#xff1a; pecl search xdebug 查询&#xff0c;找到之后用 pecl install xdebug…

C++ 类与对象中类的深入知识点+完整思维导图+基本练习题+深入细节+通俗易懂建议收藏

绪论 本章我们接着对类和对象进行探索&#xff0c;这是一个在我们c中比较重要的知识点&#xff0c;下面我们才是我们类和对象的更加深入且困难的知识点&#xff0c;希望你能通过这篇文章对类其有更加深入的了解。 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看…

【Linux】shell编程之—函数

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、概述二、函数的查看和删除1.查看 declare2.删除 declare 三、函数的返回值1.return 返回值2.echo 返回值 四、函数的参数传入与变量范围五、函数的应用1.阶乘2.…

GPT神奇应用:给孩子做每日安排

正文共 1163 字&#xff0c;阅读大约需要 4 分钟 家长必备技巧&#xff0c;您将在4分钟后获得以下超能力&#xff1a; 快速生成每日安排计划 Beezy评级 &#xff1a;B级 *经过简单的寻找&#xff0c; 大部分人能立刻掌握。主要节省时间。 推荐人 | Kim 编辑者 | Linda ●图片…

前端部署vue项目到腾讯云服务器

先把dist包上传服务器 可以使用宝塔、FileZilla、手动上传等等方式 已有腾讯云服务器之后进入面板界面 然后安装Nginx 请一步一步&#xff0c;紧跟步骤 第一步 安装gcc-c 编译器。nginx依赖的 pcre 和 zlib 包 yum -y install gcc zlib zlib-devel pcre-devel openssl openss…