当前位置: 首页 > news >正文

Linux 基础IO 二

1.文件描述符的分配规则

#include<stdio.h>
#include<string.h>
//#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{close(1);//fd分配原则,从最小的开始,没有被占用的文件描述符给新打开的文件;int fd = open("log.txt", O_CREAT | O_TRUNC | O_RDONLY, 0666);if (fd < 0){perror("open");return 1;}//按道理,都应该是往显示器(标准输出)打印的;//但是下面的都写入到了log.txt中;//这叫什么呢?输出重定向;printf("fd:%d\n", fd);//stdout在FILE中的fd=1;而printf只向1中打印,他不管1到底是谁;1原本指向的是stdout,现在成了log.txt;fprintf(stdout, "hello printf\n");const char* s = "hello fwrite\n";fwrite(s, strlen(s), 1, stdout);return 0;
}

1.1输出重定向原理:文件操作前,进程会默认关联打开三个文件标准流文件;可是已经关闭了标准输出流,相当于把files_struct arrary指针数组中的'1'位置的数据置为了NULL;可是上层面已经把stdout 设置成了‘1’;根据文件描述符分配规则;所以就写入了log.txt;

重定向的本质,其实就是在OS内部,更改fd对应的内容的指向;

1.2输入重定向

#include<stdio.h>
#include<string.h>
//#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{close(0);int fd = open("log.txt", O_RDONLY);if (fd < 0){perror("open");return 1;}printf("fd:%d\n");char buffer[64];fgets(buffer, sizeof(buffer), stdin);printf("%s\n", buffer);return 0;
}

1.3追加重定向

#include<stdio.h>
#include<string.h>
//#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{close(1);int fd = open("log.txt", O_APPEND |O_WRONLY |O_CREAT);if (fd < 0){perror("open");return 1;}fprintf(stdout,"you can see me sucessly\n");return 0;
}

2.以上全是野路子,是为了理解基本原理来写的;具体的看以下:

函数int  dup(int oldfd,int newfd)  :1:newfd  3:oldfd

#include<stdio.h>
#include<string.h>
//#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main(int argc,char* argv[])
{if (argc != 2) return 2;int fd = open("log.txt", O_CREAT |O_WRONLY |O_CREAT);if (fd < 0){perror("open");return 1;}fprintf(stdout,"%s\n",argv[1]);//stdout ->1->显示器dup2(fd, 1);  //重定向fprintf(stdout, "%s\n", argv[1]);close(fd)return 0;
}

3. 底层不同的硬件,一定对应着不同的操作方法。

但是不同的硬件都是外设,每一个设备的核心的访问函数都可以是  read  、write  (I/O)

所以:所有的设备,都有自己的read、write 但是代码的实现都不一样,就形成了类似C++的多态,调的函数名相同,但调用的不同——这样就是Linux下的一切皆文件——>VFS (virtual file system)虚拟文件系统

4.缓冲区问题

4.1什么是缓冲区? 答:就是一段内存空间

4.2为什么要有缓冲区?答:为了提高效率。如果cpu想向外设发送数据,肯定会等待多条数据一同发送到同一个外设中,而不是多次发送,所以提高了效率;主要是为了提高用户的响应速度;(写回模式)cpu太快了,相比之下磁盘太慢了,cpu等不起磁盘写入;

4.3缓冲区在哪里?谁提供?  答:

4.4缓冲区的发送数据的策率?答: 1.立即刷新  2.行刷新 (行缓冲,一般以\r,\n)3.满刷新(全缓冲:必须把缓冲区写满了,就刷新) 4.特殊情况:1.用户强制刷新(fflush) 2.进程退出,也会强制刷新;

4.5关于缓冲区的认知

一般而言,行缓冲的设备文件——是显示器

全缓冲的设备文件——磁盘文件

所有的设备,永远都倾向于全缓冲!因为缓冲区满了才刷新,意味着需要更少次的I/O操作——>更少的外设访问成本(提高效率)——cpu、内存和外设I/O的时候,数据量的大小不是主要矛盾,和外设预备I/O的过程才是最耗费时间的;其他的刷新策略,都是结合实际情况做的妥协;

显示器:是直接给用户看的,一方面要照顾效率,一方面要照顾用户体验;

极端情况下:是可以自定义规则的;

5.同样一个程序,向显示器打印输出4行文字,向普通文件(磁盘文件)打印输出7行,其中C的I/O接口打印了两次,系统接口打印了1次,和向显示器打印一样;

#include<stdio.h>
#include<string.h>
//#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{//C语言提供的fprintf(stdout, "hello fprintf\n");printf("hello printf\n");const char* s = "hello fputs\n";fputs(s, stdout);//OS提供的const char* ss = "hello write\n";write(1, ss, strlen(ss));//注意我是在最后才调用的fork,上面的函数已经跑完了fork();//创建子进程;return 0;
}

问题1:上面的测试,并不能影响系统接口!

问题迁移:上述代码用到了几个知识? 答:写时拷贝技术,将缓冲区的数据考了一份给子进程;显示器和磁盘的刷新策略不同;文件输出重定向;————对程序进行了重定向,隐形的刷新策略变成了全缓冲,\n无意义了,fork的时候,函数已经执行完了,但是数据还未刷新,父进程里的缓冲区的数据,会被子进程接收,fork之后,父子分流,之后return,父子各自退出;进程退出,强行刷新;刷新是将缓冲区数据刷给内存,也是写时拷贝(不仅仅是改变变量数据)给子进程,所以打印了两份

如果有所谓的缓冲区,我们之前所谈的缓冲区,绝对不是由操作系统提供的,应该是由C标准库维护的,也就所谓的语言层面维护的;

5.1缓冲区在哪?答:进程启动连接了C标准库,缓冲区就是C标准库中开辟的一段内存空间,fputs数据,就是把数据写入到了这段内存空间中,在由标准库调用系统接口,压入磁盘;

5.2以上说的缓冲区是C标准库给我们提供的用户级缓冲区;也就是还存在内核级缓冲区;file结构体中也是存在内核缓冲区的,一旦使用write写入内核缓冲区,就代表和进程无关了;

5.3结构体file对象中,不止由fd,还有与缓冲区相关的类型指针

6.实战:自己设计用户缓冲区,minishell支持重定向;

#include<stdio.h>
#include<string.h>
//#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<assert.h>
#include<stdlib.h>struct my_file
{int fd;int end;  //当前缓冲区的结尾;char buffer[1024];
};
typedef struct my_file my_file;my_file* fopen_(const char* pathname, const char* mode) 
{assert(pathname);assert(mode);my_file* fp = NULL;if (strcmp(mode, "r") == 0)//C语言用的穷举,C++直接map,里面放lamda就行;{}else if (strcmp(mode, "w") == 0){int fd = open(pathname, O_WRONLY | O_TRUNC | O_CREAT,0666);if (fd >= 0){fp = (my_file*)malloc(sizeof(my_file));memset(fp, 0, sizeof(my_file));fp->fd = fd;}}return fp;
}
void fputs_(const char* message, my_file* fp)//这个接口是由C标准库来执行
{assert(message);assert(fp);strcpy(fp->buffer + fp->end, message);fp->end += strlen(message);//刷新策略;是用户通过执行C标准库中的代码逻辑,来完成刷新;//这里效率提高,体现在哪里?因为C提供了缓冲区,那么我们减少了IO的执行次数if (fp->fd == 0){//标准输入}else if (fp->fd == 1){//标准输出if (fp->buffer[fp->end - 1] == '\n'){write(fp->fd, fp->buffer, fp->end);fp->end = 0;}}else if (fp->fd == 2){//标准错误}else{//其他文件}
}
void fclose_(my_file* fp)
{assert(fp);fflush_(fp);close(fp->fd);free(fp);
}
void fflush_(my_file* fp)
{assert(fp);if (fp->end != 0){//暂且认为刷新——其实是把数据写到了内核write(fp->fd, fp->buffer, fp->end);syncfs(fp->fd);//将数据写入磁盘fp->end = 0;}}int main()
{my_file* fp = fopen_("./log.txt,", "w");if (fp == NULL){printf("open file error");return 1;}fputs_("hello world", fp);fclose_(fp);return 0;
}

相关文章:

Linux 基础IO 二

1.文件描述符的分配规则 #include<stdio.h> #include<string.h> //#include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h>int main() {close(1);//fd分配原则&#xff0c;从最小的开始&#xff0c;没有被占用…...

找工作小项目:day15-macOS支持、完善逻辑

macOS支持、完善逻辑 目前的代码可以在Linux上完美运行编译&#xff0c;在Windows上也可以通过WSL编译运行源代码&#xff0c;但是在MacBook上却无法运行编译&#xff0c;这主要是由于macOS上没有epoll&#xff0c;取而代之的很相似的kqueue。由于操作系统不同&#xff0c;我们…...

植物大战僵尸杂交版 v2.0.88 mac版 Plants vs. Zombies 杂交版下载

特别注意&#xff1a;该游戏最低系统要求为macOS Sonoma 14.X&#xff0c;低于此系统版本的请勿下载&#xff01; 游戏介绍 植物大战僵尸杂交版是由B站UP主“潜艇伟伟迷”制作的一款结合了《植物大战僵尸》原有元素与创新玩法的游戏。这款游戏以其独特的“杂交”植物概念在B站…...

PHP中的while循环:用法、技巧与最佳实践

在PHP编程中&#xff0c;while循环是一种基本且常用的控制结构&#xff0c;用于重复执行代码块&#xff0c;直到指定条件为假。while循环在处理未知迭代次数的任务时特别有用&#xff0c;例如读取文件内容、处理用户输入或动态生成数据等。与for循环不同&#xff0c;while循环适…...

如何解决跨境传输常见的安全及效率问题?

在当今全球化的商业版图中&#xff0c;企业为了拓展国际市场和增强竞争力&#xff0c;跨境传输数据已成为一项不可或缺的业务活动。合格的数据跨境传输方案&#xff0c;应考虑以下要素&#xff1a; 法律合规性&#xff1a;确保方案符合所有相关国家的数据保护法律和国际法规&am…...

『大模型笔记』主成分分析(PCA)解释:简化机器学习中的复杂数据!

主成分分析(PCA)解释:简化机器学习中的复杂数据 文章目录 一. 主成分分析(PCA)解释:简化机器学习中的复杂数据!二. 参考文献一. 主成分分析(PCA)解释:简化机器学习中的复杂数据! 主成分分析(Principal Component Analysis,简称PCA)通过 将大型数据集中的维度减少…...

springboot与flowable(5):任务分配(表达式)

在做流程定义时我们需要给相关的用户节点指派对应的处理人。在flowable中提供了三种分配的方式。 一、固定分配 在分配用户时选择固定值选项确认即可。 二、表达式 1、值表达式 2、方法表达式 三、表达式流程图测试 1、导出并部署 导出流程图&#xff0c;复制到项目中 部署流…...

如何使用CCS9.3打开CCS3.0工程

如何使用CCS9.3打开CCS3.0工程 点菜单栏上的project&#xff0c;选择Import Legacy CCSv3.3 Porjects…&#xff0c;弹出对话框&#xff0c;通过Browse…按钮导入一个3.3版本的工程项目&#xff1b; 选择.pjt文件&#xff0c;选择Copy projects into worlkspace 右击选择P…...

Stable Diffusion 3 Medium 模型

开源SD3&#xff0c;中型版本&#xff0c;20亿参数&#xff0c;Stable Diffusion 3 Medium&#xff0c;系统内存要求32G&#xff0c;显卡6G。 a female character with long, flowing hair that appears to be made of ethereal, swirling patterns resembling the Northern Li…...

数据分析------统计学知识点(五)

回归算法 想象一下&#xff0c;你和朋友在讨论:大学生活中&#xff0c;每天学习的时间是否真的能影响期末成绩?这个问题看似简单&#xff0c;实则包含了一个潜在的关系:学习时间与成绩之间的联系。我们想要知道&#xff0c;增加学习时间是否会提高成绩&#xff0c;以及这种提…...

Superset二次开发之Git篇 git remote

背景:从GitHub clone Superset项目,基于3.0版本做二次开发,后续通过其他方式把3.0版本未做任何修改过的原始代码上传到企业GitLab库develop分支 任务:本地代码推送到GitLab库develop分支,但是两者似乎没有任何关联关系 操作步骤 克隆 Superset 3.0 版本的项目到本地: …...

记录一下PHP使用微信小程序支付

记录一下PHP使用微信小程序支付V3版本经历 官方文档&#xff1a;https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml 请详细查看文档中小程序支付接入前准备&#xff08;https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml&#xff…...

【数据结构初阶】 --- 单链表

关于链表你应该先了解这些 下图描述了物理模型和逻辑模型&#xff0c;大多数常见的其实是逻辑模型&#xff0c;但这对初学者或者掌握不扎实的同学不太友好&#xff0c;所以这里我重点讲解物理模型&#xff0c;当了解了这些细节&#xff0c;以后做题或是什么就直接画逻辑模型就…...

并发、多线程、HTTP连接数有何关系?

在计算机领域&#xff0c;"并发"、"多线程"和"HTTP连接数"是三个重要的概念&#xff0c;它们之间存在着密切的关系。本文将探讨这三者之间的联系以及它们在现代计算机系统中的作用。 一、并发的概念 并发是指系统能够同时处理多个任务或事件的能…...

鸿蒙轻内核Kconfig使用笔记

鸿蒙轻内核使用Kconfig进行图形化配置&#xff0c;本文专门讲解下鸿蒙轻内核LiteOS-M和LiteOS-A的图形化配置方法。本文中所涉及的源码&#xff0c;均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 、 https://gitee.com/openharmony/kernel_liteos_m 获取。本…...

react 0至1 案例

/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序* 最热 > 喜欢数量降序* 最新 > 创建时间降序* 1.点击记录当前type* 2.通过记录type和当前list中的type 匹配*/ import ./App.scss import avatar from ./images/bozai.png import {useState} …...

基于MCU平台的HMI开发的性能优化与实战(上)

随着汽车座舱智能化的不断演进&#xff0c;车内显示设备的数量显著增加&#xff0c;从传统的仪表盘和中控屏扩展至空调控制、扶手、副驾驶区域以及抬头显示&#xff08;HUD&#xff09;等多样化的显示单元。为了有效支持这些功能单元&#xff0c;同时控制整车成本&#xff0c;越…...

【Tkinter界面】Canvas 图形绘制(02/5)

文章目录 一、说明二、几何时使用 Canvas 组件2.1 用法2.2 简单范例2.3 对象移动2.4 对象删除2.5 文字对象显示 三、画布和画布对象3.1 画布生成函数原型3.2 使用create_xxx()方法3.3 对参数**options的解释 一、说明 Canvas&#xff08;画布&#xff09;组件为 Tkinter 的图形…...

1_常见指令【Linux中常见30个指令的学习和使用】【万字长文】

常见指令以及权限理解 开始学习linux前的注意事项 在学习linux之前&#xff0c;我们要知道linux是一个操作系统。 那操作系统是什么呢&#xff1f;&#xff08;这里只做大概了解&#xff09; 操作系统就是一个管理软硬件的软件。 它对上提供良好&#xff08;稳定、高效、安…...

每日复盘-202406014

今日关注: 这几天市场打板情绪环境转好,轻仓试错 20240614 六日涨幅最大: ------1--------301036--------- 双乐股份 五日涨幅最大: ------1--------301036--------- 双乐股份 四日涨幅最大: ------1--------301036--------- 双乐股份 三日涨幅最大: ------1--------301082-…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...