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

Linux:基础IO

文章目录

    • 一、理解"文件"
        • 1、狭义上的理解
        • 2、广义上的理解
        • 3、文件操作的认知
        • 4、系统角度
    • 二、C语言文件接口
        • 1、ls /proc/[进程id] -l 命令查看当前正在运⾏进程的信息
        • 2、stdin 和 stdout 和 stderr
    • 三、系统文件 I/O
        • 1、标志位传递的一种方法
        • 2、系统调用 open
    • 三、文件描述符fd
        • 1、write 写文件
        • 2、read 读文件
        • 3、0、1、2 文件描述符
        • 4、重定向
    • 四、理解“一切皆文件”
    • 五、缓冲区
        • 1、什么是缓冲区
        • 2、为什么要引入缓冲区机制
        • 3、缓冲类型
        • 4、fsync 将内核缓冲区刷新到外设
        • 5、简单设计libc库

一、理解"文件"

1、狭义上的理解

• ⽂件在磁盘⾥
• 磁盘是永久性存储介质,因此⽂件在磁盘上的存储是永久性的
• 磁盘是外设(即是输出设备也是输⼊设备)
• 磁盘上的⽂件 本质是对⽂件的所有操作,都是对外设的输⼊和输出 简称 IO

2、广义上的理解

• Linux 下⼀切皆⽂件(键盘、显⽰器、⽹卡、磁盘…… 这些都是抽象化的过程)

3、文件操作的认知

• 对于 0KB 的空⽂件是占⽤磁盘空间的
• ⽂件是⽂件属性(元数据)和⽂件内容的集合(⽂件 = 属性(元数据)+ 内容)
• 所有的⽂件操作本质是⽂件内容操作和⽂件属性操作

4、系统角度

• 对⽂件的操作本质是进程对⽂件的操作
• 磁盘的管理者是操作系统• ⽂件的读写本质不是通过C语⾔/C++的库函数来操作的(这些库函数只是为⽤⼾提供⽅便),⽽是通过⽂件相关的系统调⽤接来实现的

fopen,fclose…库封装了底层OS的文件系统调用!

二、C语言文件接口

1、ls /proc/[进程id] -l 命令查看当前正在运⾏进程的信息

在这里插入图片描述
其中:

  • cwd:指向当前进程运⾏⽬录的⼀个符号链接。
  • exe:指向启动当前进程的可执⾏⽂件(完整路径)的符号链接。
2、stdin 和 stdout 和 stderr
  • C默认会打开三个输⼊输出流,分别是stdin, stdout, stderr

在这里插入图片描述
stdin:标准输入 键盘文件
stdout:标准输出 显示器文件
stderr:标准错误 显示器文件

三、系统文件 I/O

1、标志位传递的一种方法

标志位传递的一种方法:
在这里插入图片描述

2、系统调用 open

在这里插入图片描述
第一个参数带路径,或只写文件名就在当前路径打开文件
flags的选项:表示打开文件的模式,每一个模式都是一个标记位

在这里插入图片描述

都是宏替换,每个标志位只有一个比特位为1

mode:权限位,在新建文件时

在这里插入图片描述
这里传的mod 参数最终的权限会受到umask的影响

可以通过umask()函数设置当前程序的权限掩码
在这里插入图片描述
在这里插入图片描述

close()把打开的文件关闭
在这里插入图片描述
在这里插入图片描述

三、文件描述符fd

1、write 写文件

在这里插入图片描述
const void *buf 可以二进制写入和文本写入

第一个参数fd就是open()的返回值,这个返回值叫文件描述符
在这里插入图片描述

2、read 读文件

在这里插入图片描述

3、0、1、2 文件描述符

Linux进程默认情况下会有3个缺省打开的⽂件描述符,分别是标准输⼊0,标准输出1,标准错误2.
在这里插入图片描述
在这里插入图片描述
是C语言提供了一个结构体 typedef XXX{…}FILE; 中一定封装了文件描述符fd!!!
在这里插入图片描述

4、重定向

更改文件描述符表的指针指向,数组下标不变

李淼换太子实现重定向:
在这里插入图片描述
原本标准输出的文件描述符是1,但关闭1后重新把1分配给fd,而printf()打印是标准输出1这个文件里面的,此时输出在log.txt文件中,这种现象就是重定向

  • 系统调用进行重定向

在这里插入图片描述

int dup2(int oldfd, int newfd);

使newfd成为oldfd的一份拷贝
在这里插入图片描述

  • 重定向:打开文件的方式+dup2

四、理解“一切皆文件”

通过封装一层驱动软件使得文件指针指向不同的操作实现多态来屏蔽底层设备的差异
在这里插入图片描述

五、缓冲区

1、什么是缓冲区

缓冲区是内存空间的⼀部分。也就是说,在内存空间中预留了⼀定的存储空间,这些存储空间⽤来缓冲输⼊或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输⼊设备还是输出设备,分为输⼊缓冲区和输出缓冲区。

2、为什么要引入缓冲区机制

在这里插入图片描述

提高使用者的效率

3、缓冲类型

在这里插入图片描述

在这里插入图片描述
显示器文件写入时:行刷新

在这里插入图片描述
普通文件:全缓存,写满时刷新
在这里插入图片描述

4、fsync 将内核缓冲区刷新到外设

在这里插入图片描述

5、简单设计libc库

my_stdio.h :

#pragma once

#include <stdio.h>

#define FLUSH_NONE 0
#define FLUSH_LINE 1
#define FLUSH_FULL 2

#define SIZE 1024

struct IO_FILE 
{
  int fileno;//文件描述符
  int flag;//打开文件方式
  char buffer[SIZE]; //模拟缓冲区
  int size;//文件大小
  int flush_mode;//刷新方式
};

typedef struct IO_FILE mFILE;

mFILE* Myfopen(const char* path,const char* mod);

void Myfclose(mFILE* f);

void Myfflush(mFILE* f);

void Myfwrite(const char* str,int len,mFILE* f);

my_stdio.c

#include "my_stdio.h"
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

mFILE* Myfopen(const char* path,const char* mod)
{
    int fd = -1;
    int flag;
    if(strcmp(mod,"r") == 0)
    {
        flag = O_RDONLY;
        fd = open(path,flag);
    }
    else if(strcmp(mod,"w") == 0)
    {
        flag = O_CREAT | O_WRONLY | O_TRUNC;
        fd = open(path,flag,0666);
    }
    else if(strcmp(mod,"a") == 0)
    {
        flag = O_CREAT | O_WRONLY | O_APPEND; 
        fd = open(path,flag,0666);
    } 
    else 
    {
        //...
    }
    if(fd < 0)
        return NULL;
    mFILE* pf = (mFILE*)malloc(sizeof(mFILE));
    if(pf == NULL)
    {
        close(fd);
        return NULL;
    }
    pf->fileno = fd;
    pf->flag = flag;
    pf->flush_mode = FLUSH_LINE;
    pf->size = 0;
    return pf;
}

void Myfflush(mFILE* f)
{
    write(f->fileno,f->buffer,f->size);
    f->size = 0;
    fsync(f->fileno);
}

void Myfwrite(const char* str,int len,mFILE* f)
{
    int j = 0;
    while(j < len)
    {
        int i = f->size;
        for(;i < SIZE &&  j  < len; i++,j++)
        {
            f->buffer[i] = str[j];
        }
        f->size = i;
        if(i == SIZE)
        {
            Myfflush(f);
        }
    }

    if(f->flush_mode == FLUSH_LINE && f->buffer[f->size - 1] == '\n')
    {
        Myfflush(f);
    }
}

void Myfclose(mFILE* f)
{
    if(f->size > 0)
        Myfflush(f);
    close(f->fileno);
    free(f);
}

相关文章:

  • 使用 pytest-mock 进行 Python 高级单元测试与模拟
  • 为什么MySQL选择使用B+树作为索引结构
  • 51串口通信实例(蓝牙模块和WiFi模块的介绍和使用)
  • 什么是零拷贝?
  • 模型蒸馏与量化技术:让AI模型“瘦身”却不“降智”的底层逻辑
  • Windows Server 搭建 RADIUS 认证服务器
  • 解决安卓recyclerView滚到底部不彻底问题
  • LeetCode每日精进:622.设计循环队列
  • Linux 病毒扫描工具 ClamAV 使用
  • 4*A100 部署 deepseek-r1-671B
  • Vue 报错error:0308010C:digital envelope routines::unsupported 解决方案
  • Web自动化之Selenium下Chrome与Edge的Webdriver常用Options参数
  • 【中等】59.螺旋矩阵Ⅱ
  • DeepSeek个人知识库
  • vscode设置自动换行
  • pnpm的基本用法
  • 【设计师专属】智能屏幕取色器Pro|RGB/HEX双模式|快捷键秒存|支持导出文档|C++ QT
  • vue3的实用工具库@vueuse/core
  • 【Unity】URP管线Shader编程实例详解 (1) : 漩涡效果shader
  • 10道Redis常见面试题速通
  • 是否担心关税战等外部因素冲击中国经济?外交部:有能力、有条件、有底气
  • 六个最伤脊柱的姿势,你可能天天在做
  • 广西隆林发生一起山洪灾害,致4人遇难
  • 新疆巴音郭楞州和硕县发生4.6级地震,震源深度10千米
  • 三方合作会否受政局变化影响?“中日韩+”智库合作论坛在沪举行
  • 雅典卫城上空现“巨鞋”形状无人机群,希腊下令彻查