【问题标题】:How to fork the youngest process如何分叉最年轻的进程
【发布时间】:2018-09-20 04:55:40
【问题描述】:

假设每当主程序收到 SIGINT 信号时,最年轻的(即最后一个分叉的)进程被分叉。换句话说:

p1 SIGINT

p1->p2 SIGINT

p1->p2->p3 

等等

我的问题是我不知道如何告诉孙辈-...-孩子分叉。

【问题讨论】:

  • 不清楚。阅读fork(2)signal(7)signal-safety(7)
  • @BasileStarynkevitch 主进程p1 接收SIGNT 然后它分叉并创建p2 进程。接下来,p1 再次接收SIGNTp2 分叉并创建p3。以此类推
  • 这里的逻辑很简单:接收到SIGINT,发送SIGINT给子进程。如果还没有子进程,调用fork()
  • 您可以使用进程组。父进程创建自己的进程组。当它收到第一个 SIGINT 时,它会创建一个孩子。此后,当它接收到 SIGINT 时,它会将信号发送到进程组。进程组中的进程处理中断;如果他们还没有分叉,他们现在就这样做,然后可以忽略中断(因为他们不会第二次分叉)。这可能有一些陷阱——但我还不确定它们是什么。并且简单地将中断沿流程链传递可能更简单。我认为孩子们可以退出进程组。
  • 不是所有的孩子都收到 SIGINT 信号吗?

标签: c unix signals fork


【解决方案1】:

你所有的进程都会收到 SIGINT 信号,所以主进程不需要告诉最年轻的进程去 fork;就让还没有fork的进程fork,其他的进程什么都不做。

【讨论】:

    【解决方案2】:

    我的问题是我不知道如何告诉 grand-grand-...-孩子们分叉。

    1. 家长应使用 SA_SIGINFO 标志安装 SIGINT 处理程序。
    2. 创建孙子后,它应该向父级 (p1) 发送信号。
    3. P1 通过其信号处理程序(处理程序的 siginfo_t 参数的 si_pid 字段)读取孙子的 pid。
    4. 当 Parent 收到 SIGINT 时,它会向孙子发送信号。
    5. 当孙子接收到信号时,它应该派生一个新子。
    6. 对新创建的子节点重复 2-5。

    另一种方法:

    1. 让父级轮询 SIGINT 信号。
    2. 当父级收到 SIGINT 时,创建子级。
    3. 在父上下文中屏蔽 SIGINT,在子上下文中等待 SIGINT。
    4. 在孩子的上下文中重复步骤 1 到 3。

    例子:

    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define CHILD_NEEDED 10
    static volatile sig_atomic_t got_sigint;
    static volatile sig_atomic_t child_created;
    
    void sigint_handler(int sig, siginfo_t *f, void *main_context) {
    
            ucontext_t *uc = main_context;
    
            // to mask SIGINT while returning from handler.
            sigaddset(&uc->uc_sigmask, SIGINT);
    
           ++child_created;
            got_sigint = 1;
    }
    
    void create_child(void)
    {
    
            pid_t pid = fork();
            sigset_t set;
            sigemptyset(&set);
    
            if (-1 == pid) {
                    perror("Fork failed\n");
                    exit(1);
            } else if (0 == pid) {
                  // Exit if expected child are created
                   if (child_created == CHILD_NEEDED) {
                        printf("New Child\nTotal Child: %d\n", child_created);
                        exit(0);
                }
                    got_sigint = 0;
                    // As parent mask is copied to child so clear child mask set.
                    sigprocmask(SIG_SETMASK, &set, NULL);
                    printf("New Child\n Please send signal to create child\n");
                    while (!got_sigint);
                    create_child();
            }
    
    }
    int main(int argc, const char *argv[]) {
    
            struct sigaction act = {.sa_sigaction = sigint_handler, .sa_mask = 0, .sa_flags = SA_SIGINFO};
            sigset_t mask;
            int status;
    
    
            parent = getpid();
    
            sigaction(SIGINT, &act, NULL);
            printf("parent\n Please send signal to create child\n");
    
            while (!got_sigint);
            // As we have returned from signal so SIGINT will be mask for parent.
            create_child();
    
           // parent will wait here.
            wait(&status);
            exit(0);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-13
      • 2012-04-19
      • 2022-01-04
      • 2013-05-23
      • 1970-01-01
      • 2013-03-20
      • 2012-05-05
      • 2013-05-26
      相关资源
      最近更新 更多