0

我正在尝试正确处理 SIGCHLD,但我无法在处理程序内获取进程的 PID,因此我可以更改结构内一个参数的值。

这是代码:

typedef struct
{
    int active_state;
    int pid;
}Worker;

typedef struct
{
    Worker worker;
    int used_state;//this can be USED or UNUSED
}WorkersTable;

WorkersTable *table; //I put this in a shared memory map and works correctly

这是处理程序的代码。在此文件中,有一个名为dead_child_pid的全局变量,我想存储要使用的死孩子的 pid。

void handler_SIGCHLD(int signal)
{
    pid_t child_pid;
    int e;
    do
    {
        child_pid=wait3(&e,WNOHANG,NULL);
    }while(child_pid>(pid_t)0);
    mark_unused=1;
}

当调用 handler_SIGCHLD 并且最后我们设置 mark_unused=1 时,将访问以下代码:

if(mark_unused)
    {
        /*put the current position at the table as unused*/
        int counter_find_pid=0;
        while(counter_find_pid<MAX_WORKERS&&table[contador_find_pid].used_state==USED&&table[counter_find_pid].worker.pid!=dead_child_pid)
        {
            counter_find_pid++;
        }
        table[counter_find_pid].used_state=UNUSED;
    }
4

1 回答 1

1
void handler_SIGCHLD(int signal)
{
    pid_t child_pid;
    int e;
    do
    {
        child_pid=wait3(&e,WNOHANG,NULL);
    }while(child_pid>(pid_t)0);
    mark_unused=1;
}

有效的wait3返回值为

  1. 一个孩子的pid
  2. 0 如果有没有改变状态的孩子
  3. -1 错误

child_pid在为 0 或 -1之前,您不会退出该循环,在这种情况下,先前的值(已死亡的子 pid)已被覆盖。您需要找到一种方法来将死去的孩子的有效 pid 保存在某个地方,同时仍处于循环中或更改循环。您可以将全局dead_child_pid放在处理程序中,但使其易变。

编辑

您想要更像这样的东西,但如果这是一个严肃的应用程序,这也需要增强,因为当您在下游处理死子数组时,可能会调用处理程序。然后,您必须考虑在操作时阻止 SIGCHLD。

// somewhere, probably global scope
volatile currentlyDeadChilren = 0;
volatile pid_t dead_children[MAX_DEAD_CHILDREN];    

void handler_SIGCHLD(int signal)
{
    pid_t child_pid;

    int e;

    do
    {
        child_pid=wait3(&e,WNOHANG,NULL);

        if (child_pid > 0)
            dead_children[currentlyDeadChildren++] = child_pid;        

    }while(child_pid>(pid_t)0);

    mark_unused=1;
}
于 2013-12-06T01:17:10.683 回答