当前位置: 首页 > 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-…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…...

【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验

2024年初&#xff0c;人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目&#xff08;一款融合大型语言模型能力的云端AI编程IDE&#xff09;时&#xff0c;技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力&#xff0c;TRAE在WayToAGI等…...

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...