0

在这里,我有一个用于信号处理和复制过程的示例代码。在这里,我想使用信号动作调用一个计时器,每一秒。它在这里工作正常,但是当我在启动和停止计时器函数之间添加我的复制过程代码时,当第一次信号发出意味着 1 秒后,我的复制过程将被终止。

在这里,我尝试了这些SIGRTMAX ,SIGUSR1, SIGALRM信号,但它们都给出了相同的结果。

为什么我的复制过程在信号发出时停止。?

代码 :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

#define SIGTIMER SIGRTMAX


timer_t KeepAliveTimerId;



void stopKeepAlive()
{
    if(KeepAliveTimerId != NULL)
    {
        timer_delete(KeepAliveTimerId);
        printf("timer delete\n");

    }
}

void  signalHandler(int signo, siginfo_t* info, void* context)
{
    if (signo == SIGTIMER)
    {
        printf("Signal Raised\n");
    }
}

int startKeepAlive()
{
    struct sigevent sigev; //signal event struct
    struct itimerspec itval;
    struct itimerspec oitval;
    struct sigaction sigact;


    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_SIGINFO;
    sigact.sa_sigaction = signalHandler;

    // set up sigaction to catch signal
    if (sigaction(SIGTIMER, &sigact, NULL) == -1)
    {
        printf("time_settime error \n");
        return -1;
    }

    //Create the POSIX timer to generate signo
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = SIGTIMER;
    sigev.sigev_value.sival_int = 2;

    if (timer_create(CLOCK_REALTIME, &sigev, &KeepAliveTimerId) == 0)
     {
        itval.it_value.tv_sec = 1;
        itval.it_value.tv_nsec = 0L;
        itval.it_interval.tv_sec = itval.it_value.tv_sec;
        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;

        if (timer_settime(KeepAliveTimerId, 0, &itval, &oitval) != 0)
        {
            printf("Error in set time \n");
            return -2;
        }
    }
    else
    {
        printf("Error in creating timer \n");
        return -3;
    }
    return 0;
}


int main()
{
    int result; 
    // Start Timer
    startKeepAlive();

    result = system("cp /mnt/bct/package.QuipC /Download/ 2>&1");
    if (result == 0)
    {
        printf("result is %d\n",result);
        //stop timer
        stopKeepAlive();
        return EXIT_SUCCESS;
    }
    printf("result is %d\n",result);
    // Stop Timer
    stopKeepAlive();
   return EXIT_FAILURE;
}
4

3 回答 3

0

只是为了确保我添加了这个:

#include <stdarg.h>
int zprintf(char *fmt, ...);
int zprintf(char *fmt, ...)
{
int rc;
char buff[100];
va_list aaa;

va_start(aaa, fmt);
rc = sprintf(buff, fmt, aaa);
va_end(aaa);

rc = write(2, buff, rc);
return rc;
}

并将信号处理程序替换为:

void  signalHandler(int signo, siginfo_t* info, void* context)
{
    if (signo == SIGTIMER)
    {
        zprintf("Signal Raised\n");
    }
    else
    {
        zprintf("Signal %d Raised\n", signo);
    }
}

...并替换了 system() 字符串,例如:

result = system("cp ../wakker/megahal-9.1.1.dld/tele/megahal.brn /tmp/ 2>&1");

它奏效了:

$ ./a.out
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
result is 0
timer delete

可能是巧合。(但未定义的行为也是巧合!)

于 2012-05-22T11:04:06.997 回答
0

您使用来自http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html的实时信号:

...未处理的实时信号的默认操作是终止接收过程...

因此,调用 system(...) 似乎会以某种方式影响您的信号处理程序。我会建议(正如 Wildplasser 已经提到的)摆脱明显的错误(信号处理程序中的 printf)。在上面的链接下,您还有可以在信号处理程序中使用的很好的函数列表(Async-signal-safe functions 段落)。完成后,请告诉我们是否有任何不同。

于 2012-05-22T10:32:20.967 回答
0

我编译了这段代码(对原始代码的微小变化——添加了显式void参数列表,并#define _XOPEN_SOURCE 700获取timer_t声明,简化了信号处理程序,并在 Linux(RHEL 5)上进行了链接和测试,-lrt因为 Mac OS Xtimer_t在下面的任何标题中都没有/usr/include— 使用更简单的命令来执行(echo、sleep、echo),并得到看似合理的输出:

Started
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Signal Raised
Done
result is 0
timer delete

我由此推断时序信号不会影响由 运行的命令system(),因为它们确实不应该。

gcc -Wall -Wextra -g -O3 -std=c99 sau.c -o sau -lrt

-std=c99选项可能说明我需要指定_XOPEN_SOURCE. 如果我可以费心用 编译-std=gnu99,它可能就不需要了。

代码

#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

#define SIGTIMER SIGRTMAX

timer_t KeepAliveTimerId;

void stopKeepAlive(void)
{
    if(KeepAliveTimerId != NULL)
    {
        timer_delete(KeepAliveTimerId);
        printf("timer delete\n");
    }
}

void  signalHandler(int signo)
{
    if (signo == SIGTIMER)
    {
        printf("Signal Raised\n");
    }
}

int startKeepAlive(void)
{
    struct sigevent sigev; //signal event struct
    struct itimerspec itval;
    struct itimerspec oitval;
    struct sigaction sigact;

    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = signalHandler;

    // set up sigaction to catch signal
    if (sigaction(SIGTIMER, &sigact, NULL) == -1)
    {
        printf("time_settime error \n");
        return -1;
    }

    //Create the POSIX timer to generate signo
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = SIGTIMER;
    sigev.sigev_value.sival_int = 2;

    if (timer_create(CLOCK_REALTIME, &sigev, &KeepAliveTimerId) == 0)
     {
        itval.it_value.tv_sec = 1;
        itval.it_value.tv_nsec = 0L;
        itval.it_interval.tv_sec = itval.it_value.tv_sec;
        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;

        if (timer_settime(KeepAliveTimerId, 0, &itval, &oitval) != 0)
        {
            printf("Error in set time \n");
            return -2;
        }
    }
    else
    {
        printf("Error in creating timer \n");
        return -3;
    }
    return 0;
}

int main(void)
{
    int result; 
    // Start Timer
    startKeepAlive();

    result = system("echo Started; sleep 10; echo Done");
    if (result == 0)
    {
        printf("result is %d\n",result);
        //stop timer
        stopKeepAlive();
        return EXIT_SUCCESS;
    }
    printf("result is %d\n",result);
    // Stop Timer
    stopKeepAlive();
   return EXIT_FAILURE;
}
于 2012-05-23T15:27:46.327 回答