c-fork():子进程检查父进程是否已死亡的方法



背景

我正在用C编写一个与LD_PRELOAD动态链接的共享库,用于拦截和覆盖来自预加载应用程序的网络调用,如socket()connect()recv()send()等。

在库的init中,我用pthread_create()启动了一个线程。这个线程轮询一些内核内存,这些内存被映射到用户空间。

该库的通用性足以处理(但不限于)网络基准应用程序,如netperfiperfsockperf

我的问题

一切都很好,生活在大多数情况下都是甜蜜的,只有一种例外。停用的应用程序。例如,如果我作为deamon启动netserver(netperf基准测试应用程序的服务器端),即在没有-D参数的情况下,应用程序首先要做的事情之一就是调用fork()。在fork上,父级使用exit(EXIT_SUCCESS)关闭,子级侦听连接。父级退出的事实扼杀了我的轮询线程。

因此,我想实现的是,如果父母已经离开,让孩子产生一个新的轮询线程。我可以拦截并覆盖fork()调用,但从根本上讲,我如何让孩子知道父母是否已经离开?我不能接受任何假设,因为库必须是通用的。

谢谢。

您可以定期轮询getppid()函数。一旦它开始返回"1"(init进程的id),您的父级就死了。

更新

摘录自"man pthread_create":

新线程以以下方式之一终止:。。。

  • 进程中的任何线程调用exit(3)或主线程从main()执行返回。这导致所有进程中的线程

因此,如果您的线程是由调用exit的netserver进程创建的,那么这个线程将被终止

您可以使用ptread_atfork(3)在子线程中启动线程。

大约一年后,我自己的问题得到了答案,那就是"一个子进程如何知道它的父进程已经死了?">

那么,孩子可以使用getppid()询问其父母的PID是什么。如果父PID为1,则意味着子进程已重定为init进程。因此,这位家长已经走了。

例如:

void child_fork(void)
{
int parent_pid;
usleep(1);
parent_pid = (int)getppid();
if (parent_pid == 1)
run_my_polling_thread();
}

注意:当进程分叉时,父进程将进入睡眠状态。首先运行子进程,然后唤醒父进程(对于写时复制优化,我不在这里详细介绍)。usleep(1)调用是为了让孩子立即进入睡眠状态,这样父母就有时间醒来并终止。在孩子醒来之前,它将被重新分配到init

现在,在lib初始化时,我只需要调用:

__register_atfork(NULL, NULL, child_fork, NULL)

但是,这种解决方案并不适用于所有情况。例如,如果父母有多个孩子怎么办?我真的希望他们都启动一个轮询线程吗?

现在这对我来说是一个可以接受的解决方案,尽管并不理想。

相关内容

最新更新