Linux-内存文件

news2024/12/23 20:44:43

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 3

int 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
            //5
            int 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 {
            //father
            int 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.coloradmin.cn/o/1613413.html

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

相关文章

浏览器数据找回

网站上分享的文章应该都是个人的心血&#xff0c;对于一些操作问题导致心血丢失真的很奔溃&#xff0c;终于找到一个弥补的办法&#xff0c;csdn的文章谷歌浏览器亲测有效&#xff0c;理论上其他浏览器的其他网站应该也可以&#xff0c;适用以下场景 把博客编辑当成了编写新博…

【Linux】虚拟机与Xshell及VS Code的连接

一、基础环境 虚拟机&#xff1a;VMware Workstation Pro 虚拟机镜像&#xff1a;ubuntu-18.04.5-desktop-amd64.iso 其他&#xff1a;Xshell 6、Xftp 6、Visual Studio Code 上述软件的安装操作不再赘述&#xff0c;CSDN上有大量的优秀博文&#xff0c;可参考&#xff1a;详细…

【树莓派Linux内核开发】入门实操篇(虚拟机Ubuntu环境搭建+内核源码获取与配置+内核交叉编译+内核镜像挂载)

【树莓派Linux内核开发】入门实操篇&#xff08;虚拟机Ubuntu环境搭建内核源码获取与配置内核交叉编译内核镜像挂载&#xff09; 文章目录 【树莓派Linux内核开发】入门实操篇&#xff08;虚拟机Ubuntu环境搭建内核源码获取与配置内核交叉编译内核镜像挂载&#xff09;一、搭建…

【Hadoop】- YARN架构[7]

前言 Yarn架构是一个用于管理和调度Hadoop集群资源的系统。它是Hadoop生态系统的一部分&#xff0c;主要用于解决Hadoop中的资源管理问题。 通过使用Yarn架构&#xff0c;Hadoop集群中的不同应用程序可以共享集群资源&#xff0c;并根据需要动态分配和回收资源。这种灵活的资…

强固型工业电脑在称重系统+叉车电脑,称重量体扫码一体机,物流分拣线工作站行业应用

称重系统叉车电脑行业应用 背景介绍 在叉车上安装称重传感器&#xff0c;通过对举升压力的自动检测&#xff0c;将压力信号转换为电流或电压信号&#xff0c;经过A/D转换&#xff0c;使模拟信号变为数字信号&#xff0c;经微处理器进行数据处理后通过蓝牙、串口或者USB接口将称…

java的单元测试和反射

单元测试 就是针对最小的功能单元&#xff0c;编写测试代码对其进行正确性测试 Junit单元测试框架&#xff1a; 可以用来对方法进行测试 有点&#xff1a; 可以灵活的编写测试代码&#xff0c;可以针对某个方法进行测试&#xff0c;也支持一键完成对全部方法的自动发测试&a…

【C++初阶】vector使用特性 vector模拟实现

1.vector的介绍及其使用 1.1 vector的介绍 vector文档介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#…

分类神经网络1:VGGNet模型复现

目录 分类网络的常见形式 VGG网络架构 VGG网络部分实现代码 分类网络的常见形式 常见的分类网络通常由特征提取部分和分类部分组成。 特征提取部分实质就是各种神经网络&#xff0c;如VGG、ResNet、DenseNet、MobileNet等。其负责捕获数据的有用信息&#xff0c;一般是通过…

第24天:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

第二十四天 一、PHP文件管理-显示&上传功能实现 如果被抓包抓到数据包&#xff0c;并修改Content-Type内容 则也可以绕过筛查 正常进行上传和下载 二、文件上传-$_FILES&过滤机制实现 无过滤机制 黑名单过滤机制 使用 explode 函数通过点号分割文件名&#xff0c;…

Spring Boot | Spring Boot 默认 “缓存管理“ 、Spring Boot “缓存注解“ 介绍

目录: 一、Spring Boot 默认 "缓存" 管理 :1.1 基础环境搭建① 准备数据② 创建项目③ 编写 "数据库表" 对应的 "实体类"④ 编写 "操作数据库" 的 Repository接口文件⑤ 编写 "业务操作列" Service文件⑥ 编写 "applic…

【 AIGC 研究最新方向(下)】面向平面、视觉、时尚设计的高可用 AIGC 研究方向总结

目前面向平面、视觉、时尚等设计领域的高可用 AIGC 方向有以下 4 种&#xff1a; 透明图层生成可控生成图像定制化SVG 生成 本篇&#xff08;下篇&#xff09;介绍 3、4&#xff0c;上篇在&#xff1a;https://blog.csdn.net/weixin_44212848/article/details/138035279?spm…

【FFmpeg】视频与图片互相转换 ( 视频与 JPG 静态图片互相转换 | 视频与 GIF 动态图片互相转换 )

文章目录 一、视频与 JPG 静态图片互相转换1、视频转静态图片2、视频转多张静态图片3、多张静态图片转视频 二、视频与 GIF 动态图片互相转换1、视频转成 GIF 动态图片2、 GIF 动态图片转成视频 一、视频与 JPG 静态图片互相转换 1、视频转静态图片 执行 ffmpeg -i input.mp4 …

初始化Git仓库时应该运行哪个命令?

文章目录 初始化Git仓库时&#xff0c;你应该运行git init这个命令。这个命令的作用是在你当前所在的目录里创建一个新的Git仓库。这样&#xff0c;你就可以在这个目录里开始使用Git来管理你的文件了。 下面我给你举个详细的例子来说明一下&#xff1a; 首先&#xff0c;你需要…

# 从浅入深 学习 SpringCloud 微服务架构(三)注册中心 Eureka(3)

从浅入深 学习 SpringCloud 微服务架构&#xff08;三&#xff09;注册中心 Eureka&#xff08;3&#xff09; 段子手168 1、eureka&#xff1a;高可用的引入 Eureka Server 可以通过运行多个实例并相互注册的方式实现高可用部署&#xff0c; Eureka Server 实例会彼此增量地…

Spark和Hadoop的安装

实验内容和要求 1&#xff0e;安装Hadoop和Spark 进入Linux系统&#xff0c;完成Hadoop伪分布式模式的安装。完成Hadoop的安装以后&#xff0c;再安装Spark&#xff08;Local模式&#xff09;。 2&#xff0e;HDFS常用操作 使用hadoop用户名登录进入Linux系统&#xff0c;启动…

ChatGPT研究论文提示词集合2-【形成假设、设计研究方法】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 目录 1.形成假设 2.设计研究方法 3.书籍介绍 AIPaperPass智能论文写作平台 近期小编按照学术论文的流程&#xff0c;精心准备一套学术研究各个流程的提示词集合。总共14个步骤&#…

Llama3新一代 Llama模型

最近&#xff0c;Meta 发布了 Llama3 模型&#xff0c;从发布的数据来看&#xff0c;性能已经超越了 Gemini 1.5 和 Claud 3。 Llama 官网说&#xff0c;他们未来是要支持多语言和多模态的&#xff0c;希望那天赶紧到来。 未来 Llama3还将推出一个 400B大模型&#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…

安装和部署maven

准备工作 maven下载地址&#xff1a;https://maven.apache.org/download.cgi 使用wget将maven包下载到linux环境上&#xff0c;/toos/ 目录下&#xff08;也可用迅雷&#xff09; wget https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.g…

PaddleOCRV4训练自己的模型(4)------模型推理及导出

一、Det模型推理&#xff1a; &#xff08;1&#xff09;上一篇文章只讲了推理的实现方法&#xff0c;没有展示结果&#xff0c;这里顺带展示一下结果。 因为训练定位模型的时候是整图训练&#xff0c;所以推理的时候也是整图推理。 &#xff08;2&#xff09;在推理的时候可以…