【问题标题】:A Daemon that kills a child process in a signal handler and forks a new process in c/unix一个守护进程,它在信号处理程序中杀死一个子进程并在 c/unix 中创建一个新进程
【发布时间】:2014-11-17 03:50:31
【问题描述】:

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

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

修订的处理程序和处理程序调用的函数:

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

即使我从命令行中终止子进程,进程 # 仍保持打开状态,但命令名称从“mole 2”更改为“(mole)”:

718 ?? 0:00.01 ./精神

719 ?? 0:00.00(摩尔)

725 ?? 7:48.36 摩尔 2

【问题讨论】:

  • 孩子的fopen不应该是“w+”吗?如果这不起作用,请尝试使用日志文件的完整路径。此外,使用 fsopen 进行共享打开,以防某些其他进程已经打开文件以进行写入或存在僵尸子进程。
  • mole 程序的日志文件名中的反斜杠让人联想到 Windows — 在 Linux 上极为罕见。使用access()fopen() 存在TOCTOU(检查时间,使用时间)问题。您应该简单地使用fopen(filename, "a"),因为如果文件不存在,它将创建文件,如果文件确实存在,则不会截断文件,并且所有写入都将始终发生在最后(因此fseek() 也无关紧要) .

标签: c unix daemon


【解决方案1】:

您的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 程序将尝试在根目录中创建它的日志文件——但它应该不能写入到根目录中的文件根目录。

您不应以用户root 运行测试代码或以root 开发。太危险了。

我观察到,虽然可以将一个精致的、生产就绪的守护进程放入后台,没有日志文件、标准输出和标准错误连接到/dev/null,但它使调试变得非常困难。由于很少有程序没有错误,您基本上应该始终将您的守护进程与标准输出和标准错误连接到日志文件(以附加模式打开,因此如果您截断日志文件,写入仍将发生在结束时现在截断的文件)。对于守护进程,您可能应该记录每条消息的时间,并且很可能还应该记录 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

'(24) Bad address' 错误是因为我只修复了使用execv() 的三个位置中的两个;修复第三个消除了错误。可以看到错误处理的发展;第一组没有确定哪个“执行失败”消息造成了麻烦;第二组显示它“执行失败(2)”,这使得看到问题变得微不足道。边看边学!

使用“睡眠者醒了,敬礼……”是一个(坏)笑话和混淆;它只是显示随着时间的推移循环的迭代。 (参见维基百科的Wachet aufChristians Awake, Salute the Happy Morn。)

这显示了您的代码在工作。我不相信 SIGCHLD 信号有任何相关性,但我把它们留在了里面。无论如何,孩子们很快就会死去,而不是因为被发送了 SIGCHLD。我还没有检查过僵尸——当心睡死人。

【讨论】:

  • 我真的是 unix 编程的新手(你可能知道)。我更改了目录并添加了空字符,以便它可以找到鼹鼠程序并且这似乎有效。但是我仍然有几个问题:1)我似乎找不到mole程序应该创建的日志文件。 2)我仍然无法杀死子进程我也同意调试这个程序是一场噩梦——但我不确定如何创建一个记录每条消息的时间和PID的日志。
  • 可以让父进程负责将摩尔标准输出和标准错误连接到适当的日志文件。例如,您可以创建一个目录/tmp/mole-logs 并在其中放置日志文件,可能在日志文件名中包含日期/时间和/或 PID。然后,mole 程序只需将适当的消息写入其标准输出,该信息将在您知道其位置的文件中。或者您可以编写mole 程序来打开一个文件并将其写入已知位置。两者都有效。
  • 我建议仔细查看信号处理程序中的工作量。标准 C 几乎允许您调用 signal() 来重置信号处理程序,调用 _exit()_Exit() 来终止,并修改 volatile sigatomic_t 变量。 POSIX 更加宽容,但您应该查看 How to avoid using printf() in a signal handler 以了解更多关于允许和不允许的信息(提示:printf()sprintf() 是不允许的,即使在 POSIX 中也是如此;严格来说,即使 strlen() 也是不允许的'不允许!)。
  • 最后,我建议您更新您的问题,添加修改后的代码(请不要覆盖原始代码)。我会尽可能地查看它,但是有一个叫做“工作”的不方便的东西必须时不时地给予一些关注。
  • 我在我的 cmets 中添加了关于 printfs 的修改后的代码。处理程序可以调用使用 printfs 的函数吗?我相信这个程序是有效的,只是它不会杀死痣……这当然是一个大问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
  • 2021-05-18
  • 1970-01-01
  • 2015-02-25
  • 2014-04-12
  • 2016-08-23
  • 2012-11-01
相关资源
最近更新 更多