0

假设这个程序在后台运行。

假设包含标头,例如 signal.h ...

void SignalHandler(int sig);
int fd;
int main(int argc, char *argv[]){


signal(SIGINT,SignalHandler);
signal(SIGHUP,SignalHandler);
signal(SIGTERM,SignalHandler);

setsid();
close(0);
close(1);
close(2);


fd = open("/myPIPE", O_RDWR);
if(fd<0){
perror("open() error");
exit(1);
}

while (1) {
        err = read(fd, strbuf, 256);
        if(err)
            syslog(LOG_INFO,"%s",strbuf);   

        }
close(fd);

}

void SignalHandler(int sig){

if(fd!=-1)
close(fd);
exit(0);

}

假设此代码已经在运行。并具有测试信号的程序名称。当我在终端 ./testsignal 中再次运行它时,进程只会继续加起来。当前正在运行的进程应该退出,新进程应该替换旧进程。所以只有进程应该运行。我需要这方面的帮助。谢谢

4

1 回答 1

0

此代码是您的简化代码,因为它不使用syslog(). 它也不会关闭标准输入、标准输出和标准错误,所以守护进程仍然有办法将信息记录到标准输出(特别是)。这让我更容易测试。

flprintf()函数用于确保所有输出到标准输出的输出都被刷新;它减少了程序中无聊的 4 行代码块的数量。该程序还记录了更多的活动,这也使得查看正在发生的事情变得更容易。(部分原因是我设法忽略了注释掉的close()系统调用。)我将所有在源文件之外不需要可见的东西都设为静态;这意味着 onlymain()不是静态的。此代码还确保读取的字符串以空值结尾,因此长字符串后跟短字符串不会产生短字符串加上较长字符串剩余部分的混搭的消息。

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>

static void flprintf(const char *fmt, ...);
static void SignalHandler(int sig);
static int fd = -1;

int main(int argc, char **argv)
{
    int nbytes;
    char strbuf[257];

    if (argc > 1)
    {
        int pid = atoi(argv[1]);
        if (kill(pid, SIGINT) != 0)
            flprintf("Failed to deliver SIGINT to PID %d\n", pid);
        else
            flprintf("SIGINT successfully delivered to PID %d\n", pid);
    }

    flprintf("Starting - %d\n", (int)getpid());

    signal(SIGINT, SignalHandler);
    signal(SIGHUP, SignalHandler);
    signal(SIGTERM, SignalHandler);

    setsid();
    //close(0);
    //close(1);
    //close(2);

    fd = open("./myPIPE", O_RDWR);
    if (fd < 0)
    {
        perror("open() error");
        exit(1);
    }

    flprintf("Starting read loop\n");

    while ((nbytes = read(fd, strbuf, sizeof(strbuf)-1)) > 0)
    {
        strbuf[nbytes] = '\0';
        flprintf("<<%s>>\n", strbuf);
    }

    flprintf("Read EOF - %d exiting\n", (int)getpid());

    close(fd);
    return(0);
}

void SignalHandler(int sig)
{
    flprintf("Received signal %d - %d exiting\n", sig, (int)getpid());
    if (fd != -1)
        close(fd);
    exit(0);
}

static void flprintf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
    fflush(stdout);
}

我在 Mac OS X 10.7.5(GCC 4.7.1,在这种情况下并不重要)上进行了测试。一旦它工作,我发现唯一令人惊讶的行为是,当向 FIFO 写入消息的进程关闭时,程序没有得到 EOF。但是,我认为这可以通过O_RDWR通话open()来解释;仍然有一个进程(这个)打开了 FIFO。重新编译O_RDONLY并在第一次写入管道......健全规则后退出进程。作为一种实现从不报告 EOF 的 FIFO 的方式,您所做的一切都很好。(这也解释了为什么进程在打开时没有阻塞,等待进程打开 FIFO。)

样本输出:

$ ./sig >> sig.out &
[1] 47598
$ cat sig.out
Starting - 47598
Starting read loop
$ echo "Testing, 1, 2, 3" > myPIPE
$ cat sig.out
Starting - 47598
Starting read loop
<<Testing, 1, 2, 3
>>
$ echo "Another test - 1, 2, 3" > myPIPE
$ echo "Mini test - 1, 2" > myPIPE
$ cat sig.out
Starting - 47598
Starting read loop
<<Testing, 1, 2, 3
>>
<<Another test - 1, 2, 3
>>
<<Mini test - 1, 2
>>
$ ./sig 47598 >> sig.out &
[2] 47610
$ cat sig.out
Starting - 47598
Starting read loop
<<Testing, 1, 2, 3
>>
<<Another test - 1, 2, 3
>>
<<Mini test - 1, 2
>>
Received signal 2 - 47598 exiting
SIGINT successfully delivered to PID 47598
Starting - 47610
Starting read loop
[1]-  Done                    ./sig >> sig.out
$ echo "Testing, 1, 2, 3" > myPIPE
$ cat sig.out
Starting - 47598
Starting read loop
<<Testing, 1, 2, 3
>>
<<Another test - 1, 2, 3
>>
<<Mini test - 1, 2
>>
Received signal 2 - 47598 exiting
SIGINT successfully delivered to PID 47598
Starting - 47610
Starting read loop
<<Testing, 1, 2, 3
>>
$ kill 47610
$ cat sig.out
Starting - 47598
Starting read loop
<<Testing, 1, 2, 3
>>
<<Another test - 1, 2, 3
>>
<<Mini test - 1, 2
>>
Received signal 2 - 47598 exiting
SIGINT successfully delivered to PID 47598
Starting - 47610
Starting read loop
<<Testing, 1, 2, 3
>>
Received signal 15 - 47610 exiting
[2]+  Done                    ./sig 47598 >> sig.out
$ 
于 2012-10-22T04:12:54.417 回答