c - 当进程再次执行时,使用 signal.h 终止在后台运行的进程

标签 c linux signals

假设该程序在后台运行。

假设包含 header ,例如 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 中再次运行它时,该进程会继续添加..当前正在运行的进程应该退出,新进程应该取代旧进程。所以只有进程应该在运行。我需要这方面的帮助。谢谢

最佳答案

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

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

#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。但是,我认为这是通过 open() 调用中的 O_RDWR 来解释的;仍然有一个进程(这个进程)的 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
$ 

关于c - 当进程再次执行时,使用 signal.h 终止在后台运行的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13004221/

相关文章:

linux - 如何使用 read 命令仅读取字符串的某些部分?

python - 同步两个异相的噪声正弦信号

c - 是否应该始终转换 printf 参数?

linux - 适用于 Linux 的随处运行的静态链接 gcc 二进制文件

c - lex 和 yacc 输出

linux - 在 linux 启动时运行脚本

python - PyQt 跨线程信号

c - 如何在 SIGSEGV 处理程序中安全地转储内存。 C、Linux

c - 在循环中使用 read 和 malloc 时防止 Ctrl+C 后泄漏

c - 同步udp广播文件传输