Linux-内存文件

1. 基础IO操作

1.1 c语言的IO接口

fopen:打开一个文件,按照指定方式

参数:filename 文件名,也可以是路径,mode:打开方式

返回打开的文件指针

fread:从指定流中读数据

参数:从FILE对象中读数据,每次读size字节大小的数据,最多读count次,读的数据写在buffer里 

返回实际读的数据个数

fwrite:把数据写到指定的流中

参数 :从buffer中读数据,每次读size字节大小的数据,最多读count次,读的数据写在stream里 

返回实际写的数据个数

fclose:关闭打开的文件

不同的语言,比如c,c++,java....都有对应的IO接口,语言的底层封装的其实都是操作系统对应的IO接口,在语言层面

好处有:使用方便,学习成本低,一套接口,在不同的操作系统下都可以使用,具有跨平台可移植性

1.2 Linux的IO接口

open:打开文件

参数:pathname 路径名称,flags:标记位,打开方式,mode:文件属性(新建)

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

参数:

  • O_RDONLY: 只读打开
  • O_WRONLY: 只写打开
  • O_RDWR : 读,写打开     这三个常量,必须指定一个且只能指定一个
  • O_CREAT : 若文件不存在,则创建它。需要使用mode选项(0666-umask),来指明新文件的访问权限
  • O_APPEND: 追加写
  • O_TRUNC:清空写

返回值:成功:新打开的文件描述符 失败:-1

读fd文件,写到buf里,读count字节

读buf内容,写到fd文件里,写count字节

关闭文件


2. 文件描述符fd

open函数返回值是int类型的fd,这个fd是什么呢?

我们在写代码,调用接口,然后文件被编译运行,形成进程,也就是进程在打开文件。

打开文件是进程在执行,打开文件,就是把文件从,磁盘加载到内存上,还需要一个标识符,让进程能够找到这个内存上的文件。这个标识符就是fd,file describe 文件描述符。通过fd,进程就能找到对应的文件,完成下面的操作。

一个进程,可能要打开多个文件,就会有多个fd,如何对fd进行管理呢?

而现在知道,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来 描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进 程和文件关联起来。

每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件 描述符,就可以找到对应的文件

c库默认会打开3个文件:stdin标准输入,stdout标准输出,stderr标准错误

他们的fd分别对应0(键盘),1(屏幕),2(屏幕)

接下来新建的文件,就会从3开始,依次往下,

文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。


3. 文件重定向

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{close(1);int fd = open("myfile", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);fflush(stdout);close(fd);exit(0);
}

此时,我们发现,本来应该输出到显示器上的内容,输出到了文件 myfile 当中,其中,fd=1。这种现象叫做输出重定向。常见的重定向有:>, >>, <

那重定向的本质是什么呢?

可以使用系统提供的函数接口:dup2

使用这个函数也可以达到相同的效果

dup2(3,1);

文件重定向:

输出重定向open(O_WRONLY | O_CREAT | O_APPENT)stdout重定向到新目标
追加重定向open(O_WRONLY | O_CREASE | O_TRUNC)stdout重定向到新目标
输入重定向open(O_RDONLY )stdin重定向到新目标

stdout和stderr的使用区分

stdout是用来输出打印信息,stderr一般用来输出程序的报错记录

./proc > out.txt 2> err.txt

可以分开把stdou输出的内容重定向到out.txt,stderr输出的内容重定向到err.txt

./proc > all.txt 2>&1

把两个都输出到all.txt文件中

myshell实现文件重定向

//整体结构:创建子进程,由子进程获取指令,父进程判断完成的怎么样
//1.打印标识开头
//2.获取指令字符串
//3.分析字符串提取指令到grev[]
//4.部分指令的特殊处理,例如cd
//5.替换进程execvpe
//
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>#define SIZE 1024
#define NUM 32#define EMPTY 0
#define INPUTDIR 1
#define OUTPUTDIR 2
#define APPPUTDIR 3int status_dir;char str[SIZE];
char* _grev[NUM];
char _env[NUM][NUM];char* getfile(char* str, int end)
{while(str[end] != ' '){if(str[end] == '>'){if(str[end - 1] == '>'){status_dir = APPPUTDIR;str[end-1] = '\0';return &str[end+1];}status_dir = OUTPUTDIR;str[end] = '\0';return &str[end+1];}else if(str[end] == '<'){status_dir = INPUTDIR;str[end] = '\0';return &str[end+1];}else{end--;}}return NULL;
}int main()
{int num_env = 0;status_dir = EMPTY;while(1){//1.printf("[root$loadhost myshell]# ");fflush(stdout);//2.memset(str,SIZE,'\0');fgets(str, SIZE, stdin);int sz = strlen(str);str[sz - 1] = '\0';//3.int end = sz - 2;char* file_end = getfile(str, end);_grev[0] = strtok(str, " ");int index = 1;//4.if(strcmp(_grev[0],"ls") == 0){_grev[index++] = (char*)"--color=auto";}if(strcmp(_grev[0], "ll") == 0){_grev[0] = (char*)"ls";_grev[index++] = (char*)"--color=auto";_grev[index++] = (char*)"-l";}while(_grev[index++] = strtok(NULL, " "));if(strcmp(_grev[0], "cd") == 0){if(_grev[1]) chdir(_grev[1]);continue;}if(strcmp(_grev[0], "export") == 0 && _grev[1]){memcpy(_env[num_env],_grev[1],strlen(_grev[1])+1);putenv(_env[num_env]);num_env++;continue;}pid_t id = fork();if(id < 0){perror("fork");exit(1);}else if(id == 0){//child//5int fd;switch (status_dir){case INPUTDIR:fd = open(file_end, O_RDONLY);dup2(fd,0);break;case OUTPUTDIR:fd = open(file_end, O_WRONLY | O_CREAT | O_TRUNC, 0666);dup2(fd,1);break;case APPPUTDIR:fd = open(file_end, O_WRONLY | O_CREAT | O_APPEND, 0666);dup2(fd,1);break;case EMPTY:break;default:printf("bug?\n");break;}execvp(_grev[0], _grev);exit(2);}else {//fatherint status = 0;pid_t ret = waitpid(id, &status, 0);if(ret < 0){printf("等待子进程失败\n");exit(2);}else{if(WIFEXITED(status)){printf("子进程退出码:%d\n",WEXITSTATUS(status));}else if(WIFSIGNALED(status)){printf("子进程终止信号:%d\n",WTERMSIG(status));}}}}return 0;
}

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

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

相关文章

Vuex 的原理

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store&#xff08;仓库&#xff09;。“store” 基本上就是一个容器&#xff0c;它包含着你的应用中大部分的状态 ( state )。 Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的…

没有理由不加倍努力

最近su7很火&#xff0c;各隐藏大佬都纷纷从后台来到前台&#xff0c;把整个网红界的网红等级提升了好几个档次。红衣大叔更是借此机会在疯狂地打造自己的网红IP。 千亿大佬都这还般努力&#xff0c;作为平民的自己哪还有不努力的理由。 加倍努力&#xff01;

29 共享内存

共享内存区是最快的IPC形式&#xff0c;一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;不再执行进入内核的系统调用来传递彼此的数据 原理 系统在内存中申请一段空间&#xff0c;通过页表映射挂接到进程的共享区&#…

Linux--链表 第二十五天

1. 链表 t1.next -> data t1.next->next->data .(点号)的优先级比->的大 所以 t1.next->data 就可以了 不用(t1.next)->data 2. 链表的静态增加和动态遍历 打印链表算法&#xff0c; void printLink(struct Test *head) { struct Te…

剑指Offer题目笔记32(拓扑排序)

面试题113&#xff1a; 解决方案&#xff1a; 将课程看成图中的节点&#xff0c;如果两门课程存在先修顺序那么它们在图中对应的节点之间存在一条从先修课程到后修课程的边&#xff0c;因此这是一个有向图。可行的修课序列实际上是图的拓扑排序序列。图中的每条边都是从先修课…

Web前端框架/库/工具

前言 前端从步枪&#xff08;原生js&#xff09;到了半自动武器&#xff08;jQuery&#xff09;并进化为全自动武器&#xff08;三大框架&#xff08;angular&#xff0c;react&#xff0c;vue及其生态链&#xff09;&#xff09;。 常说工欲善其事必先利其器。对于那些想要提…

【c++11】看完立马就懂--右值引用!!!

右值引用 一、什么是右值&#xff1f;什么是左值&#xff1f;二、右值引用三、右值引用的好处四、万能引用五、完美转发 一、什么是右值&#xff1f;什么是左值&#xff1f; 首先&#xff0c;当我们看到右值的时候&#xff0c;我们很自然的就会产生疑问&#xff1f; 什么的右边…

黑马鸿蒙学习5:LIST容器

LIST容器&#xff0c;其实就是如果FOREACH容器展示不全的话&#xff0c;会自动有滚动条了。要注意的是&#xff0c;LIST中必须有固定的listitem这个项&#xff0c;而且列表里面只能包含一个根组件。 必须把ROW容器放到listitem中&#xff0c;如下&#xff1a;

51、图论-岛屿数量

思路&#xff1a; 该问题要求在一个由 1&#xff08;表示陆地&#xff09;和 0&#xff08;表示水&#xff09;组成的二维网格中&#xff0c;计算岛屿的数量。岛屿被水包围&#xff0c;并且通过水平或垂直连接相邻的陆地可以形成。这个问题的核心是识别并计数网格中相连的陆地…

CSV解析

一直以为csv靠逗号&#xff08;,&#xff09;分割数据&#xff0c;那么只要用str.spilt(,,row)便可以将数据分割开。 事实证明想简单了&#xff0c;csv里还有这样的规定&#xff0c;如果数据内有双引号&#xff08;"&#xff09;和逗号&#xff08;,&#xff09;那么&…

车载电子电器架构 —— 售后诊断开发

车载电子电器架构 —— 售后诊断开发 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己…

在Postgres中,如何有效地管理大型数据库的大小和增长

文章目录 一、定期清理和维护1. VACUUM和ANALYZE2. 删除旧数据和归档 二、分区表三、压缩数据四、配置优化1. 调整维护工作负载2. 监控和日志 五、使用外部存储和扩展1. 外部表和FDW2. 扩展和插件 六、定期备份和恢复测试结论 管理大型数据库的大小和增长是数据库管理员&#x…

Java中的变量与常量

标识符 Java语言规定标识符由任意顺序的字母、下划线&#xff08;_&#xff09;、美元符号&#xff08;$&#xff09;和数字组成&#xff0c;并且第一个字符不能是数字。标识符也不能是Java中的关键字&#xff08;保留字&#xff09;。 在Java语言中&#xff0c;标识符的字母…

环境监测系统--------MQ系列气体检测模块驱动教程(保姆级教程)

⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩在环境检测中我们经常会用到检测气体的传感器&#xff0c;检测乙醇、甲烷、一氧化碳、氢气等等&#xff0c;博主呕心沥血对MQ系列传感器做一个史上最详细的使用教程…

网络安全产品---堡垒机

what 在网上搜索 运维审计与风险控制系统就是是堡垒机 我认为的堡垒机就是提供高效运维、认证管理、访问控制、安全审计和报表分析功能的云服务设备 实现高效运维的同时最大程度控制运维风险。 how 能够对运维人员维护过程进行全面跟踪、控制、记录、回放 支持细粒度配置…

政企版 WPS Pro 专业版注册安装教程

政企版 WPS Pro 专业版安装及激活步骤 第 1 步&#xff1a;下载压缩包&#xff08;内含注册码&#xff09;【无解压密码】。 第 2 步&#xff1a;解压缩后&#xff0c;运行 exe 文件&#xff0c;默认步骤安装即可。 第 3 步&#xff1a;安装完成后&#xff0c;新建一个 Word …

使用QQ邮箱进行登录验证

使用场景不多说&#xff0c;接下来直接看实现~ 登录到QQ邮箱&#xff0c;进入设置 打开IMAP/SMTP服务&#xff0c;记得把授权码记录下来&#xff0c;后面配置文件中需要用到 新建application的配置文件 spring:mail:# 指定邮件服务器地址host: smtp.qq.comusername: 你自己的q…

ROS 2边学边练(31)-- 管理大工程

前言 往往现实中的工程都是会包含很多节点很多参数很多主题的那种&#xff0c;如果单独通过各种ros2 run命令进行启动管理&#xff0c;恐怕难以招架&#xff0c;主要还是通过launch文件的方式进行管理&#xff0c;而launch文件也可以像节点那样按功能的不同模块化&#xff0c;最…

【学习】黑盒测试用例设计方法都有哪些

在软件测试中&#xff0c;黑盒测试是一种重要的测试方法&#xff0c;它专注于软件的外部行为&#xff0c;而不关心其内部结构和实现。黑盒测试的目标是确保软件的功能符合需求规格说明书中的要求。为了有效地进行黑盒测试&#xff0c;需要设计合理的测试用例。本文将详细介绍黑…

【Android】Activity task和Instrumentation杂谈

文章目录 activity taskInstrumentation机制参考 Android不仅可以装载众多的系统组件&#xff0c;还可以将它们跨进程组成ActivityTask&#xff0c;这个特性使得每个应用都不是孤立的。 activity task 从数据结构角度看&#xff0c;Task有先后之分&#xff0c;源码实现上采取了…