向儿童流程发送信号,Sigcont,Sigstop

发布于 2025-02-07 14:58:55 字数 1280 浏览 2 评论 0原文

我的代码有问题,

我希望所有孩子在程序启动时停止。 之后,我只希望带有i索引的孩子继续执行,而其他孩子则被停止。

我想在此顺序p0,p1,p2,p3,p4,p0,p1中执行它们。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#define N 5

void handler(int i)
{
    if (i == SIGCONT)
    {
        printf("signal cont\n");
    }
}
int main()
{
    int pid[N];
    for (int i = 0; i < N; i++)
    {
        if ((pid[i] = fork()) == 0)
        {
            /* code */
            while (1)
            {
                printf("ici fils %d\n", i);
                usleep(50000);
            }
        }
        else
        {
            kill(pid[i], SIGSTOP);
            // kill(pid[i], SIGSTOP);
            if (i == N - 1)
            {
                kill(pid[i], SIGCONT);
                sleep(2);
                kill(pid[i], SIGSTOP);
                kill(pid[0], SIGCONT);
            }
            else
            {

                kill(pid[i], SIGCONT);
                sleep(2);
                kill(pid[i], SIGSTOP);
                kill(pid[i + 1], SIGCONT);
            }
            // kill(pid[i], SIGKILL);
            waitpid(pid[i], NULL, 0);
        }
    signal(SIGCONT, &handler);
    }
}

I have a problem with my code,

I want all the children stop when the program start.
and after that I want just the child with the index of i to continue executing and others to be stopped .

I want to execute them in this order p0 ,p1,p2,p3,p4,p0,p1....
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#define N 5

void handler(int i)
{
    if (i == SIGCONT)
    {
        printf("signal cont\n");
    }
}
int main()
{
    int pid[N];
    for (int i = 0; i < N; i++)
    {
        if ((pid[i] = fork()) == 0)
        {
            /* code */
            while (1)
            {
                printf("ici fils %d\n", i);
                usleep(50000);
            }
        }
        else
        {
            kill(pid[i], SIGSTOP);
            // kill(pid[i], SIGSTOP);
            if (i == N - 1)
            {
                kill(pid[i], SIGCONT);
                sleep(2);
                kill(pid[i], SIGSTOP);
                kill(pid[0], SIGCONT);
            }
            else
            {

                kill(pid[i], SIGCONT);
                sleep(2);
                kill(pid[i], SIGSTOP);
                kill(pid[i + 1], SIGCONT);
            }
            // kill(pid[i], SIGKILL);
            waitpid(pid[i], NULL, 0);
        }
    signal(SIGCONT, &handler);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏末 2025-02-14 14:58:55

您的代码有几个问题,其中包括:

  1. 通过sigstop停止的任何进程一定不得注册该信号的处理程序。注册处理程序会使处理程序的行为替换 停止过程的默认行为。

  2. 注册sigcont的处理程序通常是个坏主意。这样做不会阻止sigcont继续进行该过程,这是sigcont的特殊特征,这可能令人惊讶,但是每当sigcont时,处理程序也会发射也可以交付,即使该过程没有停止,这通常是另一种惊喜。

  3. 您仅在第一个叉子后才在父级中注册信号处理程序。后来分叉的孩子将继承这些孩子,但第一个不会。除其他外,这将阻止第一个孩子的pape()不受父母发送给它的信号的阻止。您可以将每个孩子自行注册任何需要的处理程序,也可以在第一个叉子之前在父母中注册。

  4. 每个孩子的pape()与父母的第一个kill()针对该孩子的比赛。孩子可以在调用pause()之前接收sigcont,在这种情况下,它将等待 next 信号。您可以通过在分叉之前在父级中阻止sigcont,并使用适当的掩码在子里使用sigsuspend(),而不是初始暂停( )。在这种情况下,您可能要解开sigcont从该初始sigsuspend()。。

  5. 父母试图向尚未分配的进程发送信号(kill(pid [i + 1],sigcont);)。

目前尚不清楚您要实现的全部行为是什么,但是您可能要先求所有孩子,然后才开始发送信号。

更新

关于对问题的更新,

  1. 您显然想在子过程中反复循环,但是您的代码仅通过它们运行一次。这是实施我上面已经提出的内容的一个很好的理由:首先要分叉所有孩子,然后单独执行所有信号。

There are several issues with your code, among them:

  1. Any processes to be stopped via SIGSTOP must not have a handler registered for that signal. Registering a handler causes the handler's behavior to replace the default behavior of stopping the process.

  2. It's usually a bad idea to register a handler for SIGCONT. Doing so will not prevent a SIGCONT from continuing the process, which is a special characteristic of SIGCONT that can be surprising, but also the handler will fire whenever a SIGCONT is delivered, even if the process was not stopped, which is often a different kind of surprise.

  3. You register your signal handlers only in the parent, after the first fork. The subsequently forked children will inherit those, but the first one will not. Among other things, this will prevent the first child's pause() from being unblocked by the signals the parent sends to it. You can make each child register any needed handlers for itself, or you can register them in the parent, before the first fork.

  4. There is a race between each child's pause() and the parent's first kill() targeting that child. It is possible for the child to receive the SIGCONT before it calls pause(), in which case it will wait for the next signal. You can prevent that by blocking SIGCONT in the parent before forking, and using sigsuspend() in the child, with an appropriate mask, instead of the initial pause(). In that case, you probably want to unblock SIGCONT after returning from that initial sigsuspend().

  5. The parent attempts to send signals to processes that it has not forked yet (kill(pid[i + 1], SIGCONT);).

It's not clear what the full behavior you are trying to achieve is, but you may want to fork all the children first, and only then start sending signals.

Update

With respect to the update to the question,

  1. You apparently want to cycle repeatedly through the child processes, but your code runs through them only once. This is a good reason to implement what I already suggested above: fork all the children first, then, separately, do all the signalling.
梦断已成空 2025-02-14 14:58:55

child 过程中,而不是使用 <代码>暂停(2) ,使用 提高(3) 发出通话过程,以停止使用sigstop。无需注册信号处理程序。

parent 过程中,创建 child 进程后,请使用 waitpid(2) 带有wuntraced flag设置。 wifstopped(...)宏可用于专门确定孩子的状态。 wcontinue标志可用于等待 child 继续进行,就像在有wifcontinued(...)宏观之前一样。

这是一个粗略的示例,没有有意义的错误处理。请注意,同时睡觉虽然很简单,但从技术上讲,这并不是安排事物的一致方法。在执行之间,该程序的输出 May 略有不同。

#define _POSIX_C_SOURCE 200809L
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#define CHILDCOUNT 5

sig_atomic_t looping = 1;

void handler(int sig) {
    (void) sig;
    looping = 0;
}

pid_t create_child(void) {
    pid_t pid = fork();

    if (!pid) {
        /* child */
        raise(SIGSTOP);
        pid_t self = getpid();
        printf("SIGCONT in %d\n", self);

        while (1) {
            printf("RUNNING in %d\n", self);
            sleep(1);
        }

        /* bug net */
        exit(EXIT_SUCCESS);
    }

    return pid;
}

void killwait(pid_t pid, int sig) {
    kill(pid, sig);

    int status;
    waitpid(pid, &status, WUNTRACED | WCONTINUED);

    if (WIFSTOPPED(status))
        printf("P: C(%d) STOPPED!\n", pid);
    if (WIFCONTINUED(status))
        printf("P: C(%d) CONTINUED!\n", pid);
    if (WIFSIGNALED(status) && SIGKILL == WTERMSIG(status))
        printf("P: C(%d) SUCCESSFULLY KILLED!\n", pid);
}

int main(void) {
    pid_t pids[CHILDCOUNT];

    /* tentative: catch this in all processes so the parent may reap manually */
    signal(SIGINT, handler);

    for (size_t i = 0; i < CHILDCOUNT; i++) {
        pid_t current = pids[i] = create_child();

        printf("Parent now has child (%d) [#%zu].\n", current, i);
        killwait(current, 0);
    }

    for (size_t i = 0; looping; i = (i + 1) % CHILDCOUNT)  {
        pid_t current = pids[i];

        printf("P: C(%d) STARTING [#%zu].\n", current, i);

        killwait(current, SIGCONT);
        sleep(2);
        killwait(current, SIGSTOP);
    }

    for (size_t i = 0; i < CHILDCOUNT; i++)
        killwait(pids[i], SIGKILL);
}

In the child processes, instead of using pause(2), use raise(3) to signal the calling process to stop with SIGSTOP. There is no real need to register signal handlers.

In the parent process, after creating a child process, wait for it to stop (or terminate) by using waitpid(2) with the WUNTRACED flag set. The WIFSTOPPED(...) macro can be used to specifically determine the status of the child. The WCONTINUE flag can be used to wait for a child process to continue, and like before there is the WIFCONTINUED(...) macro.

Here is a cursory example, with no meaningful error handling. Note that concurrent sleeps, while simple, are not technically a consistent way to schedule things. The output of this program may differ slightly between executions.

#define _POSIX_C_SOURCE 200809L
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#define CHILDCOUNT 5

sig_atomic_t looping = 1;

void handler(int sig) {
    (void) sig;
    looping = 0;
}

pid_t create_child(void) {
    pid_t pid = fork();

    if (!pid) {
        /* child */
        raise(SIGSTOP);
        pid_t self = getpid();
        printf("SIGCONT in %d\n", self);

        while (1) {
            printf("RUNNING in %d\n", self);
            sleep(1);
        }

        /* bug net */
        exit(EXIT_SUCCESS);
    }

    return pid;
}

void killwait(pid_t pid, int sig) {
    kill(pid, sig);

    int status;
    waitpid(pid, &status, WUNTRACED | WCONTINUED);

    if (WIFSTOPPED(status))
        printf("P: C(%d) STOPPED!\n", pid);
    if (WIFCONTINUED(status))
        printf("P: C(%d) CONTINUED!\n", pid);
    if (WIFSIGNALED(status) && SIGKILL == WTERMSIG(status))
        printf("P: C(%d) SUCCESSFULLY KILLED!\n", pid);
}

int main(void) {
    pid_t pids[CHILDCOUNT];

    /* tentative: catch this in all processes so the parent may reap manually */
    signal(SIGINT, handler);

    for (size_t i = 0; i < CHILDCOUNT; i++) {
        pid_t current = pids[i] = create_child();

        printf("Parent now has child (%d) [#%zu].\n", current, i);
        killwait(current, 0);
    }

    for (size_t i = 0; looping; i = (i + 1) % CHILDCOUNT)  {
        pid_t current = pids[i];

        printf("P: C(%d) STARTING [#%zu].\n", current, i);

        killwait(current, SIGCONT);
        sleep(2);
        killwait(current, SIGSTOP);
    }

    for (size_t i = 0; i < CHILDCOUNT; i++)
        killwait(pids[i], SIGKILL);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文