当前位置: 首页 > news >正文

Linux已程序已经运行起来了,此时把可执行文件或者动态库删除,程序会崩溃吗

1. 背景问题

  • 当程序运行的时候,如果把可执行文件删除或者把此程序依赖的动态库删除,程序会继续正常运行还是会崩溃?
  • 当程序运行的时候,如果将可执行文件覆盖或者将此程序依赖的动态库覆盖,程序会继续正常运行还是会崩溃?

这两个问题中有两个变量,一个是操作的对象,可执行文件还是依赖库;一个是操作的类型,把文件删除还是把文件覆盖。

本文通过实验的方式来记录这4种情况。

先列出结论,如下表所示:

操作对象删除覆盖:cp覆盖:mv
可执行文件程序继续运行,不崩溃

操作失败,提示文件忙。

但程序继续运行,不崩溃

程序继续运行,不崩溃
动态库程序继续运行,不崩溃程序崩溃程序继续运行,不崩溃

2. 实验代码

实验代码如下:

  • hello.c
#include <stdlib.h> #include <stdio.h> #include <string.h> void say_hello() { printf("hello\n"); return; }

hello.c中实现了一个函数say_hello(),将这个文件编译成一个动态库,名字为libhello.so。

  • hello.h
void say_hello();

hello.h中是函数say_hello()的声明。这是使用C语言开发时常用的方式。头文件中是函数的声明,没有实现,c文件是函数的实现。引用库的时候包含头文件,然后再链接库。

编译命令如下:

gcc -shared -fPIC -o libhello.so hello.c
  • main.c
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include "hello.h" int main(int argc, char **argv) { say_hello(); sleep(500); return 0; }

main.c中包含了hello.h头文件,然后在编译的时候需要链接libhello.so这个动态库,否则编译会失败,提示找不到函数say_hello()的定义。如下所示:

编译命令如下:

gcc main.c libhello.so

编译完成之后,使用ldd查看a.out依赖的动态库时会提示libhello.so找不到。如下图所示:

这个时候我们还需要把 libhello.so的路径设置到LD_LIBRARY_PATH环境变量中,命令如下:

export LD_LIBRARY_PATH=/home/wyl/exelib/:$LD_LIBRARY_PATH

设置之后,再使用ldd查看a.out依赖的库,就能看到libhello.so的位置了。如下图所示:

3. 实验记录

(1)删除可执行文件

1)rm -rf删除可执行文件

程序运行之后,通过ps -ef |grep a.out可以查看进程的pid。得到进程的pid之后,就可以使用命令 cat /proc/[pid]/maps 看到进程的文件映射信息。如下图所示,能看到进程中映射的a.out信息。

然后删除a.out,再使用cat /proc/[pid]/maps查看文件映射信息,可以看到a.out信息后边增加了一个标记deleted。

这个时候程序没有崩溃,还在运行。

a.out也没有真正从磁盘删除,只有a.out退出之后,这个文件没有程序使用之后,文件才会真正从磁盘删除。

注:

什么信息能佐证文件是不是真正从磁盘删除呢,可以通过查看inode号。ls -i a.out可以查看一个文件的inode,然后使用lsof | grep xxx来过滤这个inode号,如果inode存在,说明文件没有被删除;否则,说明被删除了。

2)移动文件

通过mv命令移动文件,把文件移动到另外一个目录,程序也会继续运行,不会崩溃。

如下图所示,是程序运行只后,执行mv a.out a.out-bak,把文件重命名,这个时候能够看到系统能自动识别出来文件发生了重命名。

上边的mv,我们并没有改变a.out的目录。这次我们继续移动a.out-bak移动到其它挂载点的目录下,那么系统就显示deleted 了,跟把a.out删除现象是一样的。如下图所示:

总结:

从上边的实验可以看出来,使用mv移动文件的时候,移动的目标位置也会影响系统的显示。

a.out原本的路径是/home/wyl/exelib,第一次移动的时候是用的命令是mv a.out a.out-bak,虽然改变了文件名称,但并没有改变a.out的路径,这个时候系统是能自动识别出来的。

第二次移动的时候使用的命令是mv a.out-bak /run/,改变了a.out的路径,这个时候系统的显示和文件被删除是相同的。

这就说明:

  • 在Linux中移动文件,如果是在一个挂载点之内移动,那么就相当于给文件重命名,内核中的inode保持不变,系统能自动识别;
  • 如果文件的移动跨了挂载点,那么就相当于将旧文件删除,然后创建了一个新的文件。

实验用的虚拟机的挂载点如下,可以看到/home/wyl/exelib所在的挂载点和/run所在的挂载点是不一样的。

(2)覆盖可执行文件

想要文件覆盖的话,我们能想到cp new old 或者mv new old。但是我们如果想要覆盖可执行文件的话,使用cp无法操作成功,提示文件正忙。我们只能使用mv的方式。

使用mv的方式覆盖文件之后,系统显示和文件被删除是一样的,都是在a.out后边标记了deleted。如下图所示:

(3)删除或覆盖动态库

删除或者覆盖动态库的时候,和删除或者覆盖可执行文件的时候,现象是基本相同的。

只有一点不一样,就是cp old.so new.so时可以执行成功的,并且这个操作会导致程序崩溃。

mv是删除旧的,创建新的;cp是覆盖旧文件的内容。

http://www.jsqmd.com/news/808872/

相关文章:

  • 终极指南:5分钟掌握通达信缠论可视化插件的完整教程
  • 恒盛通美线直飞空派专线的时效稳定吗? - 恒盛通物流
  • 福州福人贸易有限公司:福人精板福州运营中心,引领饰面板行业的设计时尚与环保标杆 - 品牌策略师
  • 工业建筑板材服务商 - GrowthUME
  • 杭州地区优质劳动仲裁律师综合分析与推荐 - GrowthUME
  • Ubuntu 22.04升级后,Chrome总提示‘连接中断’?别急着重装,试试这个代理设置修复法
  • 虫草食用方法哪家最实用?搞懂这些,少走90%弯路 - GrowthUME
  • 手把手教你用TI AWR1843和mmWave SDK 03.05.00.04跑通第一个雷达Demo(附Visualizer连接避坑指南)
  • Arduino OTA升级踩坑实录:ESP8266/ESP32网络端口不显示的5个原因及解决办法
  • Simulink建模避坑指南:Selector模块处理可变大小信号时,为什么输出会变成NaN?
  • 怎么用 Shell 脚本实现 Docker 容器自动重启监控?
  • 别再买错了!Type-C充电头、Type-C接口和Type-C电源插头到底有啥区别?
  • 常州裕达集装箱移动房源头厂家:打造高品质装配式建筑新标杆 - GrowthUME
  • Ledger中国官方购买指南:三大渠道直达正品,数字资产安全无忧 - GrowthUME
  • 2026无锡地下室厂房外墙防水TOP4 本土服务商推荐 - 十大品牌榜单
  • 教育机构构建ai编程实验室时如何借助聚合平台简化管理
  • 从零构建VLC媒体播放器:解锁开源定制化的终极指南
  • Jetson AGX Orin 开箱即用指南:从拆箱到跑通第一个AI Demo(Win10/Ubuntu双系统实测)
  • 2026广州财税公司测评报告|口碑优选TOP4,实操选型指南 - GrowthUME
  • 微型投影仪技术解析与选购指南:从DLP原理到应用场景全攻略
  • 揭阳家长起名观念转变:为什么越来越多人选择正规国学起名服务 - GrowthUME
  • 首次使用Taotoken控制台进行用量分析与账单查看的直观体验
  • ledger国内怎么买?官方入口的查找与确认方法 - GrowthUME
  • 2026年无锡充电桩运营系统与社区生态物联解决方案深度横评指南 - 精选优质企业推荐官
  • Elasticsearch终极指南:如何用es-client轻松管理你的集群和数据
  • 从生物进化到APP推广:聊聊演化博弈论如何解释‘爆款’的诞生与消亡
  • 想找性价比高的板式家具创意?这里有你想要的答案! - GrowthUME
  • Tuna插件如何解决直播中音乐信息同步的痛点?
  • 2026年培育钻婚戒哪个品牌好?6大品牌深度横评,附选购避坑指南 - GrowthUME
  • 2026年国内做得好的抗静电地板厂家推荐,硅酸钙抗静电地板/环氧树脂自流平抗静电地板,抗静电地板厂家找哪家 - 品牌推荐师