linux函数深入探索——open函数打开文件是否将文件内容加载到内存空间

转自:https://blog.csdn.net/qq_17019203/article/details/85051627

问题:open(2)函数打开文件是否将文件内容加载到内存空间

首先,文件打开后都会产生一个文件描述符fd,这个文件描述符其实是记录在PCB的文件描述符表中,而这个文件描述符实质上是一个结构体,用来存放跟打开文件相关的信息,基于此前提,我产生了两种假设

1、文件描述符结构体中只存储了文件在硬盘中的相应地址信息,并不将文件内容加载到内存中,这样做的好处是减少内存空间的占用,但大大增加了运行的时间(cpu存取内存数据的速度约ns级别,cpu存取硬盘数据的速度约为60000ns)。

2、文件描述符结构体为文件在内存中分配了地址空间来存放文件内容,这样做的好处是增加了运行速度,不足是当文件太大时严重占用内存空间。

3、如果问题2正确就产生了另一个问题,这块地址空间的大小和分配规则是什么?

接下来是我的探索过程和代码

第一步:我用open(2)函数打开了一个文件,设置连续读取文件,读取的间隔为3秒。

第二步:在读取的过程中我将还没被读取完的文件删除(另外打开一个bash,用rm命令删除)

include

bash 1

[sun@localhost file_func]$ ./a.out hello

include

[sun@localhost file_func]$ rm hello
通过以上的结果我们能看出,在文件还没被读取完时将文件删除不会影响读取程序继续读取文件内容

结论1:用open(2)函数打开文件会将文件的内容加载到内存空间

接下来我们要探索的是,这个分配的地址空间大小上限是多少,文件类型的不同会不会产生不同的结果等问题

补充:

以上实验还存在一种可能性,就是rm 的原理和unlink是一样的(即rm是通过unlink封装的),等待程序运行完才会删除文件(阻塞删除),虽然删除文件操作是在文件执行完以后,但只要执行unlink文件马上就会消失看不到(在系统界面上消失,但在硬盘上还存在)

为了探索rm是不是通过unlink封装,我又进行了以下操作

一、创建虚拟映像使用rm命令

二、通过strace命令获取rm运行时产生的系统调用,命令如下

strace -f -F -o ./log.txt a.out
三、在系统调用里查找是否存在unlink函数

include

mmap(0x3f02d8e000, 18600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f02d8e000
13697 close(3) = 0
13697 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0665bb5000
13697 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0665bb4000
13697 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0665bb3000
13697 arch_prctl(ARCH_SET_FS, 0x7f0665bb4700) = 0
13697 mprotect(0x3f02d89000, 16384, PROT_READ) = 0
13697 mprotect(0x3f0241f000, 4096, PROT_READ) = 0
13697 munmap(0x7f0665bb6000, 51177) = 0
13697 brk(0) = 0x187b000
13697 brk(0x189c000) = 0x189c000
13697 open(“/usr/lib/locale/locale-archive”, O_RDONLY) = 3
13697 fstat(3, {st_mode=S_IFREG|0644, st_size=99158576, …}) = 0
13697 mmap(NULL, 99158576, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f065fd22000
13697 close(3) = 0
13697 ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo …}) = 0
13697 newfstatat(AT_FDCWD, “hello”, {st_mode=S_IFREG|0666, st_size=0, …}, AT_SYMLINK_NOFOLLOW) = 0
13697 geteuid() = 500
13697 newfstatat(AT_FDCWD, “hello”, {st_mode=S_IFREG|0666, st_size=0, …}, AT_SYMLINK_NOFOLLOW) = 0
13697 faccessat(AT_FDCWD, “hello”, W_OK) = 0
13697 unlinkat(AT_FDCWD, “hello”, 0) = 0
13697 close(0) = 0
13697 close(1) = 0
13697 close(2) = 0
13697 exit_group(0) = ?
13696

通过以上分析,我有以下结论:

1、open(2)函数在打开文件时,是否将文件内容加载到内存空间目前无法得知,在学习的时候老师的理论是linux在读取文件时候会将文件的地址内容加载到内存,而非文件的内容。

2、第一个实验结果主观上来看,因为在删除掉被读取文件后文件还能继续读取,所以open函数打开文件是将文件内容加载到内存空间的。

但通过客观分析,我们发现我们所认为的”rm删除文件,文件不在系统界面显示就是被删除了”这种想法是不对的,因为rm删除文件是调用了unlinkat系统函数,所以虽然在文件被读取时候我们看不到被读取文件在系统中显示,但此时文件还是存在于硬盘中的,只有当被读取文件被读取完成后才会真正的被删除。
————————————————
版权声明:本文为CSDN博主「虚渊玄」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_17019203/article/details/85051627

Original: https://www.cnblogs.com/x_wukong/p/12059490.html
Author: 明明是悟空
Title: linux函数深入探索——open函数打开文件是否将文件内容加载到内存空间

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/8445/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部
最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总