【Linux】简单设计libc库

news2025/5/15 17:06:14

📝前言:

经过之间两篇文章,【Linux】基础IO(一)和【Linux】基础IO(二)的学些,我们对文件的基础IO已经有了一定的理解。
这篇文章我们来简单设计一下libc库,来复习一下文件基础IO的知识

🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏


目录

  • 一,综述
  • 二,Linux内核的_IO_FILE
  • 三,mystdio.h的编写
    • 实现
  • 四,mystdio.c的编写
    • 接口介绍
    • 实现
  • 五,test.c测试

一,综述

目标:用我们的文件实现文件的写入操作

本文主要完成三个文件的编写

  • mystdio.h:头文件,主要用于声明函数,提供接口
  • mystdio.c:源文件,用于实现头文件中声明的函数和全局变量
  • test.c:测试文件

二,Linux内核的_IO_FILE

如图,这就是C库里面,管理文件的结构体
在这里插入图片描述

三,mystdio.h的编写

  • C语言库的FILE结构体,就是struct _IO_FILE FILE结构体typedef来的
  • 目标封装:
    • IO_FILE结构体(C语言的结构体),核心参数
      • int flag :文件的刷新方式
      • int fileno:文件描述符
      • char outbuffer[SIZE]:输出缓冲区(语言层)
      • int cap:缓冲区的总容量
      • int size:缓冲区已经使用的字节数
    • myopenmywritemyfflushmyclose操作,模拟C语言里面库函数的调用

实现

  1 #pragma once
  2 
  3 #define MAXSIZE 1024
  4 
  5 #define FLUSH_N 0
  6 #define FLUSH_L 1
  7 #define FLUSH_F 2
  8 
  9 struct IO_FILE
 10 {
 11     int flag;
 12     int fileno;
 13     char outbuffer[MAXSIZE];
 14     int cap;
 15     int size;
 16 };
 17 
 18 typedef struct IO_FILE MYFILE;
 19 
 20 MYFILE* myfopen(const char* pathname, const char* mode);
 21 int myfwrite(const void* ptr, int num, MYFILE* stream); //void* ptr这使得 mfwrite 函数能够接受任意类型的数据缓冲区。                                                                                         
 22 void myfflush(MYFILE* stream);
 23 void myfclose(MYFILE* stream);                      

四,mystdio.c的编写

接口介绍

memcpy

  • 原型:void* memcpy(void* dest, const void* src, size_t n);
    • dest:目标内存区域的起始地址(需确保有足够空间)
    • src:源内存区域的起始地址(只读)
    • n:要复制的字节数(size_t 类型,通常由 sizeof 或手动计算得到)

fsync

  • 传入文件描述符,把对应的内核文件缓冲区刷新到外设(我们不用管如何刷新的,只要知道能刷新就行了)

openclose等文件的系统调用不过多赘述,如果不懂的可以这篇文章:【Linux】基础IO(一)

实现

  1 #include "mystdio.h"
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <sys/stat.h>
  5 #include <sys/types.h>
  6 #include <fcntl.h>
  7 #include <unistd.h>
  8 
  9 MYFILE* myfopen(const char* pathname, const char* mode)
 10 {
 11     // opne时,如果对不存在的文件,那就要创建文件并且初始化FILE结构体
 12     int fd = -1; // 代表 open失败
 13     // 对于不同的打开方式,我们主要通过更新它的 FILE 来体现文件不同的状态
 14     if(strcmp(mode, "r") == 0)
 15     {
 16         fd = open(pathname, O_RDONLY); // 封装系统调用
 17     }
 18     else if(strcmp(mode, "w") == 0)
 19     {
 20         fd = open(pathname, O_CREAT|O_WRONLY|O_TRUNC, 06660);
 21     }
 22     else if(strcmp(mode, "a") == 0)
 23     {
 24         fd = open(pathname, O_CREAT|O_WRONLY|O_APPEND, 06660);
 25     }
 26     if(fd < 0) return NULL; // 代表开失败了
 27     MYFILE* mf = (MYFILE*)malloc(sizeof(MYFILE)); // 申请MYFILE结构体,给新的文件
 28     if(!mf) // 分配失败
 29     {
 30         close(fd);
 31         return NULL;
 32     }
 33     mf -> fileno = fd;
 34     mf -> flag = FLUSH_L; // 我们默认用行刷新,简单一点
 35     mf -> size = 0;
 36     mf -> cap = MAXSIZE;
 37 
 38     return mf;
 39 }
 40 int myfwrite(const void* ptr, int num, MYFILE* stream)
 41 {
 42     // 语言层写到缓冲区,本质是拷贝                                                                                                                                                                          
 43     memcpy(stream->outbuffer + stream->size, ptr, num);
 44     stream -> size += num;
 45     if(stream -> size > 0 && stream -> flag == FLUSH_L && stream -> outbuffer[stream->size - 1] == '\n')
 46     {
 47         myfflush(stream);
 48     }
 49     return num;
 50 }
 51 void myfflush(MYFILE* stream)
 52 {
 53     if(stream->size > 0)
 54     {
 55         write(stream->fileno, stream->outbuffer, stream->size);
 56         // 刷新到外设
 57         fsync(stream->fileno);
 58         stream->size = 0;
 59     }
 60 }
 61 void myfclose(MYFILE* stream)
 62 {
 63     if(stream->size > 0)
 64     {
 65         myfflush(stream);
 66     }
 67     close(stream->fileno);
 68 }
 69 

五,test.c测试

测试往文件log.txt里面写入信息,看是否写入成功
代码:

  1 #include "mystdio.h"
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 
  6 int main()
  7 {
  8     MYFILE* fp = myfopen("./log.txt", "a");
  9     if(fp == NULL)
 10     {
 11         printf("打开失败");
 12         return 1;
 13     }
 14     int cnt = 3;                                                                                                                                                                                             
 15     while(cnt)
 16     {
 17         printf("write %d\n", cnt);
 18         char buffer[64];
 19         snprintf(buffer, sizeof(buffer),"hello message, number is : %d\n", cnt);
 20         cnt--;
 21         myfwrite(buffer, strlen(buffer), fp);
 22         myfflush(fp);
 23         sleep(1);
 24     }
 25     myfclose(fp);
 26     return 0;
 27 }

运行结果:
在这里插入图片描述


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

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

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

相关文章

milvus+flask山寨《从零构建向量数据库》第7章case2

继续流水账完这本书&#xff0c;这个案例是打造文字形式的个人知识库雏形。 create_context_db: # Milvus Setup Arguments COLLECTION_NAME text_content_search DIMENSION 2048 MILVUS_HOST "localhost" MILVUS_PORT "19530"# Inference Arguments…

【Canda】常用命令+虚拟环境创建到选择

目录 一、conda常用命令 二、conda 环境 2.1 创建虚拟环境 2.2 conda环境切换 2.3 查看conda环境 2.4 删除某个conda环境 2.5 克隆环境 三、依赖包管理 3.1 安装命令 3.2 更新包 3.3 卸载包 3.4 查看环境中所有包 3.5 查看某个包的版本信息 3.6 搜索包 四、环境…

【登录认证】JWT令牌

一、概述 JWT全称:**JSON Web Token **(https://jwt.io/)定义了一种简洁的、自包含的格式&#xff0c;用于通信双方以json数据格式安全的传输信息。组成: ①第一部分:Header(头)&#xff0c;记录令牌类型、签名算法等。例如: (“alg”:" HS256"," type":“…

python3:文件与异常

本来这篇教程是打算在base python数据类型之后出的&#xff0c;但是计划赶不上变化&#xff0c;反正最后都要融会贯通&#xff0c;今日有时间、今天遇到了类似的问题&#xff0c;就今天做这一模块的整理&#xff0c;顺序不是重点。 参考我的上一篇博客&#xff1a;https://blo…

【兽医电子处方软件】佳易王宠物医院电子处方管理系统:宠物医院诊所用什么软件?一键导入配方模板软件程序实操教程 #操作简单 #宠物医院软件下载安装

一、概述 软件试用版资源文件下载方法&#xff1a; 【进入头像主页第一篇文章最后 卡片按钮 可点击了解详细资料 或左上角本博客主页 右侧按钮了解具体资料信息】 本实例以 佳易王宠物医院电子处方管理系统软件 为例说明&#xff0c;其他版本可参考本实例。试用版软…

问题及解决02-处理后的图像在坐标轴外显示

一、问题 在使用matlab的appdesigner工具来设计界面&#xff0c;可以通过点击处理按钮来处理图像&#xff0c;并将处理后的图像显示在坐标轴上&#xff0c;但是图像超出了指定的坐标轴&#xff0c;即处理后的图像在坐标轴外显示。 问题图如下图所示。 原来的坐标轴如下图所…

EasyX开发——绘制跟随鼠标移动的小球

游戏主循环&#xff1a; #include<graphics.h>int main() {initgraph(1280, 720);while (true){}return 0; } peekmessage函数&#xff1a;如果成功拉取到了消息&#xff0c;函数就会返回true&#xff0c;反之就会返回false 使用另外一个循环来不断地从消息队列当中拉取…

【Qt开发】信号与槽

目录 1&#xff0c;信号与槽的介绍 2&#xff0c;信号与槽的运用 3&#xff0c;自定义信号 1&#xff0c;信号与槽的介绍 在Qt框架中&#xff0c;信号与槽机制是一种用于对象间通信的强大工具。它是在Qt中实现事件处理和回调函数的主要方法。 信号&#xff1a;窗口中&#x…

使用聊天模型和提示模板构建一个简单的 LLM 应用程序

官方教程 官方案例 在上面的链接注册后&#xff0c;请确保设置您的环境变量以开始记录追踪 export LANGSMITH_TRACING"true" export LANGSMITH_API_KEY"..."或者&#xff0c;如果在笔记本中&#xff0c;您可以使用以下命令设置它们 import getpass imp…

探索 C++23 的 views::cartesian_product

文章目录 一、背景与动机二、基本概念与语法三、使用示例四、特点与优势五、性能与优化六、与 P2374R4 的关系七、编译器支持八、总结 C23 为我们带来了一系列令人兴奋的新特性&#xff0c;其中 views::cartesian_product 是一个非常实用且强大的功能&#xff0c;它允许我们轻…

【docker】--镜像管理

文章目录 拉取镜像启动镜像为容器连接容器法一法二 保存镜像加载镜像镜像打标签移除镜像 拉取镜像 docker pull mysql:8.0.42启动镜像为容器 docker run -dp 8080:8080 --name container_mysql8.0.42 -e MYSQL_ROOT_PASSWORD123123123 mysql:8.0.42 连接容器 法一 docker e…

Ensemble Alignment Subspace Adaptation Method for Cross-Scene Classification

用于跨场景分类的集成对齐子空间自适应方法 摘要&#xff1a;本文提出了一种用于跨场景分类的集成对齐子空间自适应&#xff08;EASA&#xff09;方法&#xff0c;它可以解决同谱异物和异谱同物的问题。该算法将集成学习的思想与域自适应&#xff08;DA&#xff09;算法相结合…

如何通过 Windows 图形界面找到 WSL 主目录

WSL(Windows Subsystem for Linux)是微软开发的一个软件层,用于在 Windows 11 或 10 上原生运行 Linux 二进制可执行文件。当你在 WSL 上安装一个 Linux 发行版时,它会在 Windows 内创建一个 Linux 环境,包括自己的文件系统和主目录。但是,如何通过 Windows 的图形文件资…

深入 MySQL 查询优化器:Optimizer Trace 分析

目录 一、前言 二、参数详解 optimizer_trace optimizer_trace_features optimizer_trace_max_mem_size optimizer_trace_limit optimizer_trace_offset 三、Optimizer Trace join_preparation join_optimization condition_processing substitute_generated_column…

每日一道leetcode

790. 多米诺和托米诺平铺 - 力扣&#xff08;LeetCode&#xff09; 题目 有两种形状的瓷砖&#xff1a;一种是 2 x 1 的多米诺形&#xff0c;另一种是形如 "L" 的托米诺形。两种形状都可以旋转。 给定整数 n &#xff0c;返回可以平铺 2 x n 的面板的方法的数量。返…

CD3MN 双相钢 2205 材质保温 V 型球阀:恒温工况下复杂介质控制的高性能之选-耀圣

CD3MN 双相钢 2205 材质保温 V 型球阀&#xff1a;恒温工况下复杂介质控制的高性能之选 在石油化工、沥青储运、食品加工等行业中&#xff0c;带颗粒高粘度介质与料浆的恒温输送面临着腐蚀、磨损、堵塞等多重挑战。普通阀门难以兼顾耐高温、强密封与耐腐蚀性&#xff0c;导致设…

python酒店健身俱乐部管理系统

目录 技术栈介绍具体实现截图系统设计研究方法&#xff1a;设计步骤设计流程核心代码部分展示研究方法详细视频演示试验方案论文大纲源码获取/详细视频演示 技术栈介绍 Django-SpringBoot-php-Node.js-flask 本课题的研究方法和研究步骤基本合理&#xff0c;难度适中&#xf…

嵌入式开发学习(第二阶段 C语言基础)

综合案例《猜拳游戏》 需求&#xff1a; 本游戏是一款单机游戏&#xff0c;人机交互 规则&#xff1a; 需要双方出拳&#xff1a;石头、剪刀、布赢&#xff1a; 石头→剪刀剪刀→ 布布 →石头 两边出拳相等输&#xff1a; … 实现&#xff1a; 选择对手玩家出拳对手出拳判断胜…

YOLOv1:开启实时目标检测的新篇章

YOLOv1&#xff1a;开启实时目标检测的新篇章 在深度学习目标检测领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;系列算法无疑占据着重要地位。其中&#xff0c;YOLOv1作为开山之作&#xff0c;以其独特的设计理念和高效的检测速度&#xff0c;为后续的目标…

FFmpeg多路节目流复用为一路包含多个节目的输出流

在音视频处理领域&#xff0c;将多个独立的节目流&#xff08;如不同频道的音视频内容&#xff09;合并为一个包含多个节目的输出流是常见需求。FFmpeg 作为功能强大的多媒体处理工具&#xff0c;提供了灵活的流复用能力&#xff0c;本文将通过具体案例解析如何使用 FFmpeg 实现…