做人呢,最紧要就系开心啦

Linux多进程1:多进程的生死抉择

732次阅读
没有评论

进程调度,主要解决 CPU 资源分配问题,多进程解决如下问题:

解决生命周期问题(init,systemd);
解决进程程序背景的问题(exec)
解决进程之间通信问题(IPC)
设计进程与进程之间的界限;

1. 解决生命周期问题(init, systemd)

fork 创建子进程后,可以监控子进程退出原因;父进程死后,子进程默认挂载到 init 进程;3.4 之后的版本,添加了用 SUBREPER 来挂载孤儿进程;

systemd 分两 level
系统级 systemd,(init 进程对应的软连接),
用户级 systemd 调用 prctl(PR_SET_CHILD_SUBREPER,1)将自己设置为 subreper;

Linux 为每个用户创建一个 systemd。
Linux 多进程 1:多进程的生死抉择

若父进程先退出,子进程挂靠到对应的 systemd 根进程。
Systemd 源码:vim src/core/main.c

if (!arg_system)
1984                 /* Become reaper of our children */
1985                 if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0)                                                                   
1986                         log_warning_errno(errno, "Failed to make us a subreaper: %m");
1987

2 解决进程程序背景的问题(exec)

2.1 exec 不创建进程,它改变程序执行背景

Windows CreateProcess 创建子进程,Linux exec 不创建进程,原进程 PID 不变,只是改变程序执行背景(fork 原子进程与父进程是 COW 机制共享资源比如 MM 等,exec 是全新的);
同一个进程,执行程序一样了;
Linux 多进程 1:多进程的生死抉择

父子进程都可以改变程序环境。

2.2 vfork 没有写时拷贝

fork()依赖于硬件 MMU 实现,对于没有 MMU 的系统,用 vfork 代替,vfork 没有写时拷贝;
Linux 多进程 1:多进程的生死抉择

vfork 后,父进程什么时候继续执行?
当父进程 MM 不再被子进程共享时;

vfork 创建子进程后,父进程 阻塞等待 vfork_done,再继续往下执行;
Linux 多进程 1:多进程的生死抉择

Linux 唤醒 vfork_done 有两个地方,进程退出和 exec

所以,在子进程创建后立马调用 exec 的场景,用 vfork 更合适(可以省掉 fork 的 COW);
调用 exec 之前指向同一个 mm_struct,调用 exec 之后申请新的 mm_struct。

3 main 函数的生命周期

3.1 main 函数即不是程序的入口,也不是出口

main 函数进去之前,执行了动态库的构造函数;
main 函数退出之后,执行动态库的析构函数

注意,后注册的钩子函数先执行;

__attribute__ ((constructor))
Xxx1()
{…}
__attribute__ ((destructor))
Xxx2()
{…}

3.2 main 函数正常退出方式有:

(1)正常 / 默认退出 return 0; 会调用库函数 exit()

(2)调用库函数 exit()退出;
库函数 exit()会执行 flush io、调用 atexit()注册的钩子函数,再调用系统调用_exit(n) 退出, (n 为 return 函数返回的退出码);

strace ./a.out

(3)exit_group(1): 同 TGID 全部退出

(4)进程被信号杀掉,会调用_exit(),不会调用钩子函数,也不会执行 flush,直接退出;;

(5)调用_exit(n),非正常返回;

4.Lsan 检测内存泄漏:

实际上是调用钩子函数__lsan_do_leak_check(),它依赖返回,如果不返回则不调用;
Linux 多进程 1:多进程的生死抉择

gcc lsan.c -g -fsanitize=leak

Linux 多进程 1:多进程的生死抉择

但是如果程序不退出,或者用信号杀死,都不会执行__lsan_do_leak_check();
解决办法,实际工程上,可以 把内存泄漏检测放在捕捉信号函数 上;

gcc -shared -fPIC lsan-helper.c -o lsan-helper.so -lpthread -ldl

Linux 多进程 1:多进程的生死抉择

#include <sanitizer/lsan_interface.h>
__lsan_do_leak_check()

LD_PRELOAD 强制加载动态库

LD_PRELOAD=./lsan-helper.so  ./a.out

正文完
 
admin
版权声明:本站原创文章,由 admin 2022-01-12发表,共计1691字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)