scp 动态库导致core的原因分析

scp 动态库导致core的原因分析:

项目背景:

我们写的业务代码,编译出来是so文件,用exe进行dlopen加载so动态库。 在服务器上面,我们会使用 scp 把新编译的so拷贝到服务器上面。 这样导致的问题是core的位置不固定,杂乱无章。

原因分析:

  1. (from 和 to 都是我们编译的动态库,有正在运行的程序引用它):
    cp from to // to文件是已经存在的。 被覆盖文件 to的inode依旧不变(属性也不变),内容变为from的
    scp 172.172.xx.xx:/from to // to文件是已经存在的。 被覆盖文件 to的inode依旧不变(属性也不变),内容变为from的
    mv from to // to的inode变为from的,相应的,to的属性也成了from的

  2. 我们来看看cp/scp 系统干了什么:
    strace cp test2 test 2>&1 | grep open.*test
    open(“test2”, O_RDONLY|O_LARGEFILE) = 3
    open(“test”, O_WRONLY|O_TRUNC|O_LARGEFILE) = 4
    可见,cp的实现逻辑不是“rm + open(O_CREAT)”,而是 O_TRUNC。 执行mv的时候,老的to文件因为有进程在引用它,所以老的to文件并没有被真正删除,只是被系统给隐藏起来了;在进程重启后,系统会把隐藏的to文件删除,引用新的to文件(从from改名过来)

深层思考:

为什么文件inode不变,使用 O_TRUNC方式拷贝动态库就core呢?

这里解释下虚拟内存:
虚拟内存:用户编译生成的程序时使用的地址称为虚拟地址。使程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。 虚存空间的用户程序按照虚地址编程并存放在辅存(硬盘)中。程序运行时,由MMC依据当时分配给该程序的实地址空间把程序的一部分调入实存。每次访存时,首先判断该虚地址所对应的部分是否在实存中。如果是,则进行地址转换并用实地址访问主存;否则,发出缺页中断,将辅存中的部分程序调度进物理内存,再按同样的方法访问物理内存。 虚拟内存空间 和 物理内存的映射关系,存储在物理内存某个(或者某些)页上面,这里简称为 虚存的页

0.Linux由于Demand Paging机制的关系,必须确保正在运行中的程序镜像(注意,并非文件本身)不被意外修改,因此内核会绑定这个动态库的inode到该进程,不会变更。内核也在启动程序后会绑定 内存页 到这个so的inode,而一旦此inode文件被open函数O_TRUNC掉,则kernel会把so文件对应在 虚存的页 清空。 由于这个虚拟内存空间 和 物理内存的映射关系没有了,导致已经加载到物理内存中的部分数据也没办法访问,系统会自动回收这块物理内存。 这样当运行到so里面的代码时,因为物理内存中不再有实际的数据(仅存在于虚存空间内),会产生一次缺页中断。Kernel从so文件中copy一份到内存中去。

1.应用程序通过dlopen打开so的时候,kernel通过mmap把so加载到进程地址空间,对应于vma里的几个page.
2.在这个过程中loader会把so里面引用的外部符号例如malloc printf等解析成真正的虚存地址。
3.当so被cp覆盖时,确切地说是被trunc时,kernel会把so文件在虚拟内的页purge 掉。
4.当运行到so里面的代码时,因为物理内存中不再有实际的数据(仅存在于虚存空间内),会产生一次缺页中断。
5.Kernel从so文件中copy一份到内存中去,a)但是这时的全局符号表并没有经过解析,当调用到时就产生segment fault , b)如果需要的文件偏移大于新的so的地址范围,就会产生bus error. 全局符号表在dlopen的时候已经解析重定位过了,trunc后不会再重定位一次。

所以,如果用相同的so去覆盖
A) 如果so 里面依赖了外部符号,coredump
B) 如果so里面没有依赖外部符号,运气不错,不会coredump

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值