【Linux】简单设计libc库
📝前言:
经过之间两篇文章,【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
:缓冲区已经使用的字节数
myopen
、mywrite
、myfflush
、myclose
操作,模拟C语言里面库函数的调用
实现
1 #pragma once2 3 #define MAXSIZE 10244 5 #define FLUSH_N 06 #define FLUSH_L 17 #define FLUSH_F 28 9 struct IO_FILE10 {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:
- 传入文件描述符,把对应的内核文件缓冲区刷新到外设(我们不用管如何刷新的,只要知道能刷新就行了)
open、close等文件的系统调用不过多赘述,如果不懂的可以这篇文章:【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 }
运行结果:
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!