欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 模拟进程通过系统调用向缓冲区写入并刷新的过程

模拟进程通过系统调用向缓冲区写入并刷新的过程

2025/3/1 20:37:26 来源:https://blog.csdn.net/2301_80377335/article/details/145925891  浏览:    关键词:模拟进程通过系统调用向缓冲区写入并刷新的过程

目录

fsync

模拟进程通过系统调用向缓冲区写入并刷新的过程

my_stdio.h设计

mfopen设计

mfwrite设计

mfflush设计

mflose设计


今天我们通过几十行代码来自己做一个简单的缓冲区。

昨天有个问题没有讲清楚,如下:

父进程创建了文件并写入,那为什么子进程也可以访问到这个文件并刷新缓冲区,问题的后面昨天解答了,为什么子进程也可以访问到文件呢?

相当于子进程完完全全继承了父进程在文件描述符表的信息,这和页表的拷贝有点像的。

fsync

由于close在系统层面不会之间刷新缓冲区,我们如果要调用系统的函数来强制刷新缓冲区就需要使用fsync函数

看不懂是干什么的很正常,参数就一个,就是传一个文件描述符,fsync 负责强制把内存中的数据同步到磁盘,确保数据持久化。相当于手动的刷新对应fd文件的文件缓冲区。

但是会强制同步到磁盘,会强制执行这个操作,直接将文件挂起,fsync 会强制将数据从内存缓冲区(Page Cache)同步到磁盘,而不是让操作系统自行调度刷新,如果磁盘 I/O 负载已经很高,再次调用 fsync 会让磁盘更忙,影响其他 I/O 操作,比如数据库查询、日志写入等。

fsync 是一个阻塞操作,在数据真正落盘前,调用它的进程会被挂起,如果多个线程或进程频繁调用 fsync,可能会导致严重的性能下降,甚至造成系统卡顿。在极端情况下,如果所有进程都在等待 fsync 完成,而磁盘负载过高,可能会导致 I/O 死锁或超时问题。

怎么解决呢,它的下面还有函数可以极大的提高效率,fdatasync(fd)只同步数据,不同步元数据,所以比 fsync 更高效。

成功刷新!!!

模拟进程通过系统调用向缓冲区写入并刷新的过程

由于用户级缓冲区存在FILE结构体内部,所以我们这次主要的就是模仿文件创建,读写和刷新缓冲区的操作。这个代码总体还是特别简单的,只要你之前C语言通讯录那个代码会自己打个大概,相信这个不会太难的。

my_stdio.h设计

在mFILE结构体当中写入缓冲区buffer,这个一般是malloc出来的,但是我们这次就简单一点直接创建1024个空间就可以了,然后结构体包含元素有缓冲区刷新方式flag,三种方式如上,文件描述符,再加两个缓冲区的总容量capable和当前占用了多少size。

mFILE* mfopen(const char* filename, const char* mode);是文件创建函数,像C语言的fopen一样,传入一个待文件的地址和文件要打开并执行的模式。

int mfwrite(const char* ptr, int num, mFILE* stream);是写函数,这个二进制写在glibc里面是有四个参数的,我们简单点就3个,ptr是代写入的内容,num是写入的个数,stream是写入的文件地址。

void mfflush(mFILE* stream);是刷新缓冲区的函数,唯一参数是写入的文件地址。

 void mfclose(mFILE* stream);是关闭文件函数,唯一参数是写入的文件地址。

在.h里面完全就是准备阶段。这里有人要问了,为什么不直接包含头文件呢,我们以前都是这么干的呀,这里是因为,我们这个程序将来有可能要跨平台或跨文件去用的,只需要将.c文件弄成.o再链接别人的main.o(测试文件)就可以在被人的电脑上跑了,如果.c里面没有头文件的话就找不到了,那个.h在别人的电脑上是看不到的。

mfopen设计

C语言的创建文件函数本质在底层就是封装了系统调用的open,所以我们也只直接调用系统的open来创建,我们先判断传入的mode(文件执行方式),依照不同的执行方式进行创建不同使用权限的文件,然后返回一个fd,如果创建失败或者用户输入的mode不在比较范围那原有初始化的fd肯定不变(<0),就返回空了,在创建成功后,需要malloc一个FILE,初始化FILE里面的对象,我们再次默认刷新方式使用行刷新,最后返回值别忘了。

这部分的头文件比较多,逻辑参考如上。

mfwrite设计

创建成功文件后或者文件已经存在了,就开始写入工作,由于系统文件刷新缓冲区是调用的写函数write,但是这个过程是先写入然后刷新后再写入系统的内核缓冲区的也就是文件里面。我们这里也不直接写入,我们先默认模式是追加,所以只需要拷贝到buffer的特定位置就可以了,反正每次拷贝都会覆盖之前的而又带入新的。然后判断释放要刷新缓冲区,判断规则为buffer最后一个字符是/n,并且选择的是行刷新,最后别忘了要有数据才刷新size > 0,如果以上三个条件都满足了,那就调用mfflush函数刷新缓冲区,写入文件,否则这么写入buffer就可以了。

mfflush设计

原系统调用的是write系统调用来刷新用户级的缓冲区然后写入内存的,刷新缓冲区函数直接调用write就可以达到刷新的目的,当然你也可以再接着使用fsync来强制刷新系统级的内核的缓冲区。然后最后别忘了size重置成0。

mflose设计

这个函数呀有一个细节,由于fcloseC语言函数内部又是直接封装调用的系统调用close,所以我们等下关闭文件的时候也是调用的这个,但是在此之前需要检查一下对应的缓冲区还有没有数据,有的话需要先刷新掉。

我们等下再进行测试,设计的总体思路就是这样的。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词