转自: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

#include

#include

#include

#include

int main(int argc,char *argv[])

{

int fd;

char buf[128];

int read_size,write_size;

//open a file with read and write

fd = open(argv[1],O_RDWR);

if(fd == -1)

{

perror("open");

return 1;

}

while(1)

{

read_size = read(fd,buf,2);

if(read_size == 0) break;

write(1,buf,read_size);

sleep(3);

}

//close fd

close(fd);

return 0;

}

下面是运行结果:

bash 1

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

#include

#include

int main(int argc,char *argv[])

{

int link_flag;

link_flag = link(argv[1],argv[2]);

if(link_flag == -1)

{

perror("link");

return 1;

}

if(link_flag == 0)

printf("creat hard link success...\n");

return 0;

}

bash 2

[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

#include

#include

#include

int main(void)

{

pid_t pid;

//creat child process

pid = fork();

if(pid == -1)

{

perror("fork");

return 1;

}

//child process

if(pid == 0)

{

//load a memory

int ex_flag=execlp("/bin/rm","rm","hello",NULL);

if(ex_flag == -1)

{

perror("execlp");

return 2;

}

return 0;

}

//father process

else

{

wait(NULL);

}

return 0;

}

通过strace产生的结果如下

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 <... wait4 resumed> NULL, 0, NULL) = 13697

13696 --- SIGCHLD (Child exited) @ 0 (0) ---

13696 exit_group(0) = ?

我们可以看到倒数第8行出现了一个unlinkat系统调用函数,根据unlinkat函数的定义,第三个参数取0时,unlinkat等价于unlink。

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

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

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

但通过客观分析,我们发现我们所认为的“rm删除文件,文件不在系统界面显示就是被删除了”这种想法是不对的,因为rm删除文件是调用了unlinkat系统函数,所以虽然在文件被读取时候我们看不到被读取文件在系统中显示,但此时文件还是存在于硬盘中的,只有当被读取文件被读取完成后才会真正的被删除。

————————————————

版权声明:本文为CSDN博主「虚渊玄」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_17019203/article/details/85051627

利用PHP的debug&lowbar;backtrace函数,实现PHP文件权限管理、动态加载

简述 可能大家都知道,php中有一个函数叫debug_backtrace,它可以回溯跟踪函数的调用信息,可以说是一个调试利器. 好,来复习一下 01 one(); 02 03 function one ...

(转)利用PHP的debug&lowbar;backtrace函数,实现PHP文件权限管理、动态加载 【反射】

linux so lazyload,linux函数深入探索——open函数打开文件是否将文件内容加载到内存空间...相关推荐

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

    转自:https://blog.csdn.net/qq_17019203/article/details/85051627 问题:open(2)函数打开文件是否将文件内容加载到内存空间 首先,文件打开 ...

  2. Linux进程调用execve,实验:从整理上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和...

    学号375 转载请注明出处 https://github.com/mengning/linuxkernel/ 阅读理解task_struct数据结构 task_struct实际上就是进程PCB以下是p ...

  3. linux文件 内存映射 锁,linux – mmap:将映射文件立即加载到内存中吗?

    不,是的,也许吧.这取决于. 调用mmap通常只意味着对应用程序而言,映射文件的内容将映射到其地址空间,就像文件已加载到那里一样.或者,好像该文件确实存在于内存中,就好像它们是同一个(包括更改被写回磁 ...

  4. R语言导入数据文件(数据导入、加载、读取)、使用read.table函数导入逗号分割文件CSV(Comma Delimited Text File)

    R语言导入数据文件(数据导入.加载.读取).使用read.table函数导入逗号分割文件CSV(Comma Delimited Text File) 目录

  5. R语言导入数据文件(数据导入、加载、读取)、使用readr包中的read_csv函数导入逗号分割文件CSV(Comma Delimited Text File)

    R语言导入数据文件(数据导入.加载.读取).使用readr包中的read_csv函数导入逗号分割文件CSV(Comma Delimited Text File) 目录

  6. R语言导入数据文件(数据导入、加载、读取)、使用haven包的read_dta函数导入Stata中的dta格式文件

    R语言导入数据文件(数据导入.加载.读取).使用haven包的read_dta函数导入Stata中的dta格式文件 目录

  7. R语言导入数据文件(数据导入、加载、读取)、haven包的read_spss函数导入SPSS中的sav格式文件

    R语言导入数据文件(数据导入.加载.读取).haven包的read_spss函数导入SPSS中的sav格式文件 目录

  8. R语言导入数据文件(数据导入、加载、读取)、使用haven包的read_sav函数导入SPSS中的sav格式文件

    R语言导入数据文件(数据导入.加载.读取).使用haven包的read_sav函数导入SPSS中的sav格式文件 目录

  9. python函数 模块先加载到内存后执行_Python从内存中使用编译后的模块

    在Windows编程的时候,有些时候,我们经常会要使用一些非常规的方法,比如说从内存中加载DLL,然后使用DLL中的函数.于是就思索在用Python的时候是否能够将几个编译好的Pyc合并成一个,然后使 ...

最新文章

  1. Maya基础入门学习教程
  2. JZOJ 5107. 【GDSOI2017】 中学生数据结构题
  3. vue-cli4脚手架搭建实战教程
  4. TypeScript 入门
  5. QML基础类型之geoshape
  6. jquery完成界面无刷新加载登陆注册
  7. SQL Server 数据库维护脚本合集[005]-删除数据库所有用户表
  8. 全球领先的数据库!我用它直接让公司项目的性能提升了一半~
  9. 真香!腾讯再发阳光普照奖:每人100股,价值超6万!
  10. CSS 元素的定位之相对定位 position: relative
  11. Eclipse 下用Maven构建ssh框架web工程
  12. android 磁盘日志记录,GitHub - xflyandroid/XLog: 一个简易的日志打印框架(支持打印策略自定义,默认提供2种策略:logcat打印和磁盘打印)...
  13. 通过wvdial完成4G自动拨号上网
  14. 金融领域的数字化转型和科技创新有哪些应用?
  15. Taylor Swift为何听不到搜不到她的歌曲了?让我告诉你个好法子
  16. oracle数据错误循环冗余检查,/S-Error: (OS 23) 数据错误(循环冗余检查)
  17. Linux克隆后自动改uuid,解决克隆 Linux虚拟机后修改后的机器的ip、mac、uuid失败的问题...
  18. 李航《统计学习方法》K近邻代码
  19. FFmpeg+SDL 视频播放器
  20. abstract 的基本概念和用法

热门文章

  1. Property visible must be accessed with $ or _ are not proxied in the Vue instance to prevent错误
  2. 计算机与书法专业,临帖要像?计算机“算法”精确你的每一个像素!震惊书法圈!...
  3. cordova 调起拨打电话
  4. Sketch Less for More: On-the-Fly Fine-Grained Sketch Based Image Retrieval (CVPR 2020 Oral)
  5. 用过滤器防sql注入
  6. 算法笔记.胡凡 第九章 二叉树
  7. 手机号核验复开是什么意思?可能你涉及到这些行为了!
  8. 回收站没有刚刚删除的文件原因|找回方法|解决方案
  9. 微信局域网测试环境搭建方法
  10. java获取jira上的任务