一个守护进程,它在信号处理程序中杀死子进程并在c / unix中分叉新进程

时间:2014-11-17 03:50:31

标签: c unix daemon

我创建了一个程序来创建一个守护进程,该守护进程在收到信号后会生成并终止子进程(#34; mole")。当我向进程发送一个信号(kill -USR1 589)时,它也会杀死该守护进程......它似乎也没有执行我创建的鼹鼠程序(记录鼹鼠弹出的程序)。我做错了什么?请帮忙!!

#define MAXMOLES 2
//pid_t moles [MAXMOLES] = {-1,-1};
pid_t pid_child_mole;
int num;

void handler(int signum){
//signal handler that kills child and forks a new one OR kills child
    //and shuts down daemon
    if (signum == SIGTERM){
        kill (pid_child_mole,SIGTERM);
        exit(0);
    }
    if(signum == SIGUSR1){
        if(num == 0 && pid_child_mole > 0){
            kill(pid_child_mole,SIGCHLD);
        }
        num = rand() % 2;
        char *snum;
        sprintf(snum,"%d",num+1);
        char *mArgv[MAXMOLES] = {"mole",snum};
        pid_child_mole=fork();
            if(pid_child_mole==0){
                execv(mArgv[0],mArgv);
            }
        (void) signal(SIGUSR1, handler);
    }//if sigusr1
    if(signum == SIGUSR2){
        if(num == 1){
            kill(pid_child_mole,SIGCHLD);
        }
        num = rand() % 2;
        char *snum;
        sprintf(snum,"%d",num+1);
        char *mArgv[MAXMOLES] = {"mole",snum};
        pid_child_mole=fork();
            if(pid_child_mole==0){
                execv(mArgv[0],mArgv);
            }
        (void) signal(SIGUSR2, handler);
    }//if sigusr2
}
int main(int argc, char* argv[]){
    int fd0, fd1, fd2;
    pid_t process_id = 0;
    pid_t sid = 0;
// Create child process
    process_id = fork();
    if (process_id < 0) {// Indication of fork() failure
        printf("fork failed!\n");
        exit(1);// Return failure in exit status
    }
// PARENT PROCESS. Need to kill it.
    if (process_id > 0){
        printf("process_id of child process %d \n", process_id);
    // return success in exit status
        exit(0);
    }
//unmask the file mode
    umask(0);
    //set new session
    sid = setsid();
    if(sid < 0){
        // Return failure
        exit(1);
    }
// Change the current working directory to root.
    chdir("/");
// Close stdin. stdout and stderr
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
// Open a log file in write mode.
    //fp = fopen ("Log.txt", "w+");
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);
    (void) signal(SIGTERM, handler);
    (void) signal(SIGUSR1, handler);
    (void) signal(SIGUSR2, handler);
    //num = rand() % 2;
    pid_child_mole=fork();
    while (1)
    {
        //Dont block context switches, let the process sleep for some time
        sleep(1);
    // Implement and call some function that does core work for this daemon.
        if(pid_child_mole == 0) {
            /* This is done by the child process. */
            num = rand() % 2;
            char *snum;
            sprintf(snum,"%d",num+1);
            char *mArgv[MAXMOLES] = {"mole",snum};
            execv(mArgv[0],mArgv );
            /* If execv returns, it must have failed. */
            printf("Unknown command\n");
            exit(0);
          }

    }
    //fclose(fp);
    close(fd0);
    close(fd1);
    close(fd2);
    return (0);
}

鼹鼠计划:

int main(int argc, char* argv[]){
    char *file_contents;
    FILE *fp;
    if( access( "Lab6_Daemon\\lab6.log", F_OK ) != -1 ) {
        // file exists
        fp= fopen ("Lab6_Daemon\\lab6.log", "r+");
    } else {
        // file doesn't exist
        fp= fopen ("Lab6_Daemon\\lab6.log", "a+");
    }
    fseek(fp, 0, SEEK_END);
    char *s;
    if(strcmp(argv[1],"1") == 0)
        s="Pop mole1";
    else
        s="Pop mole2";
    fprintf(fp, "%s\n",s);
    fclose(fp);
}

REVISED处理程序&amp;处理程序调用的函数:

void handler(int signum){
//signal handler that kills child and forks a new one OR kills child
    //and shuts down daemon
    if (signum == SIGTERM){
        kill (process_id,SIGTERM);
        exit(0);
    }
    if(signum == SIGUSR1)
        processSigNum(signum,0);
    else if (signum == SIGUSR2)
        processSigNum(signum,1);
    (void) signal(signum, handler);
}

void processSigNum (int sig, int moleNum){
    static int count =0;
    printf("\nThis is moleNum: %d with PID %d", moleNum+1,pid_child_mole[moleNum]);
    if(pid_child_mole[moleNum]>0){
        kill(pid_child_mole[moleNum],SIGKILL);
        pid_child_mole[moleNum] = 0;
    }
    int num = rand() % 2;//new moleNumber
    printf("\nNEW moleNum: %d", num+1);
    char snum[2];//used to store num as a char* and increment so that is it is
                //mole 1 or 2 instead of 0 or 1
    sprintf(snum,"%d",num+1);
    char *mArgv[] = {"mole",snum,0};
    if (pid_child_mole[num] >0)
        printf("\nMOLE %d ALREADY EXISTS!!",num);
    else{
        pid_child_mole[num]=fork();
        count++;
        if(pid_child_mole[num]==0)
            execv(mArgv[0],mArgv);

    }
    printf("\n\n");
}

即使我从命令行终止子进程,进程#仍然保持打开状态,但命令名称从&#34; mole 2&#34; to&#34;(mole)&#34;:

718 ?? 0:00.01 ./spiritd  

719 ?? 0:00.00(摩尔)  

725 ?? 7:48.36摩尔2

1 个答案:

答案 0 :(得分:3)

您的execv()代码存在问题:

char *mArgv[MAXMOLES] = {"mole",snum};
execv(mArgv[0],mArgv );

参数列表需要以空指针终止:

char *mArgv[] = { "mole", snum, 0 };
execv(mArgv[0], mArgv);

此外,在处理程序代码(以及主程序)中,您有:

char *snum;
sprintf(snum,"%d",num+1);

这是致命的;你需要为snum分配空间。在这种情况下,修复很简单:

char snum[16];
sprintf(snum, "%d", num+1);

您可以使用:

char snum[16];
snprintf(snum, sizeof(snum), "%d", num+1);

但似乎没什么必要。

另一对相关问题是:

  1. 因为你cd到根目录,所以mole程序不会被发现执行,除非你在根目录中创建它 - 这将是一个令人憎恶的事情
  2. 因为cd到根目录,(如果它一直运行),mole程序将尝试在根目录中创建其日志文件 - 但是它应该无法写入到根目录中的文件。
  3. 您不应该以用户root或开发为root的方式运行测试代码。这太危险了。

    我观察到,虽然可以将抛光的,生产就绪的守护程序放入后台,而没有日志文件和标准输出以及标准错误连接到/dev/null,但它会使调试非常困难。由于很少有程序没有bug,你基本上应该总是将你的守护进程与标准输出和标准错误连接到一个日志文件(在追加模式下打开,这样如果你截断日志文件,写入仍然会在结束时发生现在被截断的文件)。对于守护进程,您应该记录每条消息的时间,并且很可能也记录PID。标准日志记录包函数可用于自动执行此操作。如果没有日志文件,您就无法可靠地报告问题,因此您将失明,并且失明会导致您绊倒并受到伤害。

    我不确定这些是唯一的问题,但它们可能足以解决您的大部分问题。


    修订mole.c

    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <unistd.h>
    
    int main(int argc, char **argv)
    {
        FILE *fp = fopen("/tmp/mole.log", "a");
        if (fp != 0)
        {
            time_t now = time(0);
            struct tm *utc = gmtime(&now);
            char timestamp[32];
            strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%SZ", utc);
            char *s;
            if (argc > 1 && strcmp(argv[1], "1") == 0)
                s = "Pop mole1";
            else
                s = "Pop mole2";
            fprintf(fp, "%s - %5d: %s\n", timestamp, (int)getpid(), s);
            fclose(fp);
        }
        return 0;
    }
    

    该程序与其前身之间的主要区别在于它使用固定的日志文件名并在日志文件中记录时间和PID。

    修订moletrap.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/stat.h>   /* umask() */
    #include <signal.h>
    #include <unistd.h>
    #include "stderr.h"
    
    static pid_t pid_child_mole;
    static int num;
    
    // signal handler that kills child and forks a new one OR kills child
    // and shuts down daemon
    static void handler(int signum)
    {
        if (signum == SIGTERM)
        {
            err_remark("Send SIGTERM to %d\n", (int)pid_child_mole);
            kill(pid_child_mole, SIGTERM);
            err_remark("Exiting\n");
            exit(0);
        }
        else if (signum == SIGUSR1)
        {
            if (num == 0 && pid_child_mole > 0)
            {
                err_remark("Send SIGCHLD to %d\n", (int)pid_child_mole);
                kill(pid_child_mole, SIGCHLD);
            }
            num = rand() % 2;
            char snum[16];
            sprintf(snum, "%d", num + 1);
            char *mArgv[] = { "mole", snum, 0 };
            pid_child_mole = fork();
            if (pid_child_mole == 0)
            {
                err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
                execv(mArgv[0], mArgv);
                err_syserr("failed (1) to execute %s %s\n", mArgv[0], mArgv[1]);
            }
            (void) signal(SIGUSR1, handler);
        }
        else if (signum == SIGUSR2)
        {
            if (num == 1)
            {
                err_remark("Send SIGCHLD to %d\n", (int)pid_child_mole);
                kill(pid_child_mole, SIGCHLD);
            }
            num = rand() % 2;
            char snum[16];
            sprintf(snum, "%d", num + 1);
            char *mArgv[] = { "mole", snum, 0 };
            pid_child_mole = fork();
            if (pid_child_mole == 0)
            {
                err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
                execv(mArgv[0], mArgv);
                err_syserr("failed (2) to execute %s %s\n", mArgv[0], mArgv[1]);
            }
            (void) signal(SIGUSR2, handler);
        }
        else
            err_remark("received unexpected signal %d\n", signum);
    }
    
    int main(int argc, char **argv)
    {
        const char *logfile = "/tmp/moletrap.log";
        err_setarg0(argv[argc - argc]);
        err_setlogopts(err_getlogopts() | ERR_STAMP | ERR_PID);
    
        // Create child process
        pid_t process_id = fork();
        if (process_id < 0)  // Indication of fork() failure
            err_syserr("fork() failed\n");
    
        if (process_id > 0)
        {
            // PARENT PROCESS exits successfully
            printf("process ID of child process %d \n", process_id);
            exit(0);
        }
    
        // unmask the file mode
        umask(0);
        // set new session
        pid_t sid = setsid();
        if (sid < 0)
            err_syserr("setsid() failed\n");
    
        // Change the current working directory to root.
        // if (chdir("/") != 0)
        //     err_syserr("chdir() failed\n");
    
        // Redirect standard input from /dev/null
        close(STDIN_FILENO);
        if (open("/dev/null", O_RDONLY) < 0)
            err_syserr("failed to open /dev/null\n");
    
        // Redirect standard output and standard error to a log file
        int fd1 = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
        if (fd1 < 0)
            err_syserr("failed to open %s\n", logfile);
        if (dup2(fd1, STDOUT_FILENO) < 0)
            err_syserr("failed to send standard output to log file %s\n", logfile);
        if (dup2(fd1, STDERR_FILENO) < 0)
            err_syserr("failed to send standard error to log file %s\n", logfile);
        close(fd1);
    
        err_remark("Started\n");
    
        (void) signal(SIGTERM, handler);
        (void) signal(SIGUSR1, handler);
        (void) signal(SIGUSR2, handler);
        pid_child_mole = fork();
        while (1)
        {
            sleep(1);
            err_remark("Sleepers awake, salute ...\n");
            if (pid_child_mole == 0)
            {
                int num = rand() % 2;
                char snum[16];
                sprintf(snum, "%d", num + 1);
                char *mArgv[] = { "mole", snum, 0 };
                err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
                execv(mArgv[0], mArgv );
                err_syserr("failed (3) to execute %s %s\n", mArgv[0], mArgv[1]);
            }
        }
    
        return(0);
    }
    

    此版本使用原始信号处理代码,疣和所有。从理论上讲,它不应该完成它在信号处理程序中所做的所有事情,但它可以正常工作。 OTOH,如果出现任何问题,除了重写代码之外别无他法。

    代码使用我的"stderr.h"标头,并隐式使用实现stderr.c。这从根本上简化了错误报告编码:err_syserr()报告错误和基于errno的系统错误消息并退出,而err_remark()写入消息并返回到调用代码。 err_setarg0()函数记录程序名称(通常基于argv[0]); err_getlogopts()报告当前日志选项设置,err_setlogopts()设置相同的值加上ERR_PID(在每行输出上记录PID)和ERR_STAMP(为每行添加时间戳)输出)。标题是150行(93个非空白,非注释行);来源是608行(424非空白,非评论行) - 太大了,不能在这里显示。如果您需要代码,请查看我的个人资料。

    示例命令序列

    $ ./moletrap        # Reported 9424
    $ kill -USR2 9424
    $ kill -USR2 9424
    $ kill -USR1 9424
    $
    
    $ ./moletrap        # Reported 9456
    $ kill -USR2 9456
    $ kill -USR2 9456
    $ kill -USR1 9456
    $ kill -USR1 9456
    $ kill -TERM 9456
    $ kill -TERM 9456
    $
    
    $ ./moletrap        # Reported 9499
    $ kill -USR2 9499
    $ kill -USR2 9499
    $ kill -USR2 9499
    $ kill -USR1 9499
    $ kill -USR1 9499
    $ kill -USR1 9499
    $ kill -TERM 9499
    $
    

    示例mole.log

    2014-11-20 05:28:49Z -  9425: Pop mole2
    2014-11-20 05:29:12Z -  9428: Pop mole2
    2014-11-20 05:33:36Z -  9457: Pop mole2
    2014-11-20 05:34:00Z -  9462: Pop mole2
    2014-11-20 05:34:02Z -  9463: Pop mole1
    2014-11-20 05:36:54Z -  9500: Pop mole2
    2014-11-20 05:37:07Z -  9501: Pop mole2
    2014-11-20 05:37:08Z -  9504: Pop mole2
    2014-11-20 05:37:09Z -  9505: Pop mole2
    2014-11-20 05:37:13Z -  9506: Pop mole1
    2014-11-20 05:37:14Z -  9507: Pop mole1
    2014-11-20 05:37:15Z -  9508: Pop mole1
    

    示例moletrap.log

    moletrap: 2014-11-19 21:28:48 - pid=9424: Started
    moletrap: 2014-11-19 21:28:49 - pid=9425: about to execute mole 2
    moletrap: 2014-11-19 21:28:59 - pid=9426: about to execute mole 2
    moletrap: 2014-11-19 21:28:59 - pid=9426: failed to execute mole 2
    error (14) Bad address
    moletrap: 2014-11-19 21:29:02 - pid=9424: Send SIGCHLD to 9426
    moletrap: 2014-11-19 21:29:02 - pid=9427: about to execute mole 2
    moletrap: 2014-11-19 21:29:02 - pid=9427: failed to execute mole 2
    error (14) Bad address
    moletrap: 2014-11-19 21:29:12 - pid=9428: about to execute mole 2
    
    moletrap: 2014-11-19 21:33:35 - pid=9456: Started
    moletrap: moletrap: 2014-11-19 21:33:36 - pid=9456: Sleepers awake, salute ...
    2014-11-19 21:33:36 - pid=9457: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:36 - pid=9457: about to execute mole 2
    moletrap: 2014-11-19 21:33:37 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:38 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:39 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:40 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:41 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:42 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:43 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:44 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:45 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:46 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:47 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:48 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:49 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:50 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:51 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:52 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:53 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:54 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:55 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:55 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:55 - pid=9460: about to execute mole 2
    moletrap: 2014-11-19 21:33:55 - pid=9460: failed (2) to execute mole 2
    error (14) Bad address
    moletrap: 2014-11-19 21:33:56 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:57 - pid=9456: Send SIGCHLD to 9460
    moletrap: 2014-11-19 21:33:57 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:57 - pid=9461: about to execute mole 2
    moletrap: 2014-11-19 21:33:57 - pid=9461: failed (2) to execute mole 2
    error (14) Bad address
    moletrap: 2014-11-19 21:33:58 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:33:59 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:00 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:00 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:00 - pid=9462: about to execute mole 2
    moletrap: 2014-11-19 21:34:01 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:02 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:02 - pid=9463: about to execute mole 1
    moletrap: 2014-11-19 21:34:03 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:04 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:05 - pid=9456: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:34:06 - pid=9456: Send SIGTERM to 9463
    moletrap: 2014-11-19 21:34:06 - pid=9456: Exiting
    
    moletrap: 2014-11-19 21:36:53 - pid=9499: Started
    moletrap: moletrap: 2014-11-19 21:36:54 - pid=9499: Sleepers awake, salute ...
    2014-11-19 21:36:54 - pid=9500: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:36:54 - pid=9500: about to execute mole 2
    moletrap: 2014-11-19 21:36:55 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:36:56 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:36:57 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:36:58 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:36:59 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:00 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:01 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:02 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:03 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:04 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:05 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:06 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:07 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:07 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:07 - pid=9501: about to execute mole 2
    moletrap: 2014-11-19 21:37:08 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:08 - pid=9499: Send SIGCHLD to 9501
    moletrap: 2014-11-19 21:37:08 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:08 - pid=9504: about to execute mole 2
    moletrap: 2014-11-19 21:37:09 - pid=9499: Send SIGCHLD to 9504
    moletrap: 2014-11-19 21:37:09 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:09 - pid=9505: about to execute mole 2
    moletrap: 2014-11-19 21:37:10 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:11 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:12 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:13 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:13 - pid=9506: about to execute mole 1
    moletrap: 2014-11-19 21:37:14 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:14 - pid=9499: Send SIGCHLD to 9506
    moletrap: 2014-11-19 21:37:14 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:14 - pid=9507: about to execute mole 1
    moletrap: 2014-11-19 21:37:15 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:15 - pid=9499: Send SIGCHLD to 9507
    moletrap: 2014-11-19 21:37:15 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:15 - pid=9508: about to execute mole 1
    moletrap: 2014-11-19 21:37:16 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:17 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:18 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:19 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:20 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:21 - pid=9499: Sleepers awake, salute ...
    moletrap: 2014-11-19 21:37:21 - pid=9499: Send SIGTERM to 9508
    moletrap: 2014-11-19 21:37:21 - pid=9499: Exiting
    

    &#39;(24)错误地址&#39;错误是因为我只修复了使用execv()的三个地方中的两个;修复第三个消除了错误。你可以看到错误处理的发展;第一组没有确定哪些“未能执行”&#39;消息给了麻烦;第二组表明它执行了#2失败(2),这使得查看问题变得微不足道。观察和学习!

    使用&#34;睡眠者醒着,敬礼......&#34;是一个(坏)笑话和混淆;它只是显示循环的迭代与时间的推移。 (请参阅维基百科的Wachet aufChristians Awake, Salute the Happy Morn。)

    这显示了您的代码在工作中。我不相信SIGCHLD信号与我们有任何关联,但是我把它们留了下来。孩子们无论如何都要及时死亡,而不是因为被送到SIGCHLD。我没有检查过僵尸 - 小心睡着了。