【问题标题】:How to deal with shared memory and shared semaphores on a fork-exec?如何处理 fork-exec 上的共享内存和共享信号量?
【发布时间】:2012-11-06 19:28:40
【问题描述】:

我想将新功能添加到已扩展的应用程序中,以使用 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 生成新进程时,处理共享内存和共享信号量的正确方法是什么?

【问题讨论】:

    标签: c multithreading exec fork shared


    【解决方案1】:

    您的死锁很可能是由于未关闭子文件描述符造成的。 在尝试其他任何事情之前先试试这个:

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

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

    【讨论】:

    • 感谢您的提示,我现在使用以下代码关闭子进程中的所有文件描述符:
    • 感谢您的提示,我现在使用以下代码关闭子进程中的所有文件描述符:
    • DIR* hdir = opendir("/proc/self/fd/"); struct dirent* 条目;诠释 fd; if (hdir != NULL) { while ((entry = readdir(hdir)) != NULL) { fd = strtol(entry->d_name, NULL, 10);如果 (fd > 2) 关闭(fd); } 关闭(hdir); }
    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

          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);
          }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-29
        • 1970-01-01
        • 2010-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        相关资源
        最近更新 更多