1

我想将新功能添加到一个成长的应用程序中,以使用 fork (2) 和 exec (3) (当前为 execl) 开始执行另一个应用程序。

不幸的是,该应用程序使用共享内存、共享信号量并且有大量打开的文件描述符,在调用 fork 时这些描述符都是重复的。我知道我应该在子进程中调用 execl 之前关闭所有文件描述符、共享资源等,但是其中一部分由第三方库处理,我无法访问它们。

最重要的是,所有应用程序都是线程化的(使用 posix 线程),但只要子进程中的 fork 和 exec 之间没有异步系统调用(根据http://www.linuxprogrammingblog.com/threads -and-fork-think-twice-before-using-them )。

我现在面临的问题是 execl 调用似乎以某种方式破坏了共享资源,导致使用它们的线程出现死锁。这似乎只在调用 execl 时发生,因为在使用 _exit (2) 的 fork 后立即退出子进程不会产生这种行为。

使用 fork 和 exec 生成新进程时,处理共享内存和共享信号量的正确方法是什么?

4

3 回答 3

1

这里可能存在多个问题,包括 fork() 和 exec() 代码中的错误,甚至是程序使用共享内存和信号量的方式中的错误。

处理此问题的一种可能方法是使用system()函数。

这将在 shell 环境中运行命令并阻塞,直到程序退出。您可以生成一个新线程,然后调用 system. 让内置函数处理正确的 fork() 和 exec()。

如果您仍然有问题,那么我会说您的共享内存/信号量与 fork 和 exec 不兼容。

于 2012-11-06T20:22:30.900 回答
1

您的死锁很可能是由于未关闭子文件描述符造成的。在尝试其他任何事情之前,请尝试以下操作:

遍历子文件中的所有文件描述符/proc/[pid]/fd并在调用之前关闭它们exec

如果这不起作用,那么您必须将所有内存(除了堆栈帧之外)标记MADV_DONTFORKmadvise. 您可以通过将映射范围与本地线程堆栈上的任何指针进行比较来获取所有当前映射的列表/proc/[pid]/maps和本地堆栈帧。

于 2012-11-07T01:41:13.497 回答
1

我现在用来关闭所有文件描述符的代码再次在这里(在评论中看起来不太好)。

    DIR* hdir = opendir("/proc/self/fd/");
    struct dirent* entry;
    int fd;

    if (hdir != NULL) {
        while ((entry = readdir(hdir)) != NULL) {
            fd = strtol(entry->d_name, NULL, 10);

            if (fd > 2)
                close(fd);
        }

        closedir(hdir);
    }

那关闭了我十几个文件描述符。

于 2012-11-07T11:00:09.570 回答