这里我有一个信号处理和复制过程的示例代码。 在这里,我想每秒使用信号动作调用一个计时器。 它的工作正常,但是当我在启动和停止计时器功能之间添加我的复制过程代码时,我的复制过程将在第一次发出信号时被杀死,这意味着在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;
}
答案 0 :(得分:0)
您使用来自http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html的实时信号:
... 未处理的实时信号的默认操作是终止 接收过程......
所以看来调用system(...)会以某种方式影响你的信号处理程序。我建议(如已经提到的wildplasser)摆脱明显的错误(信号处理程序中的printf)。在上面的链接中,你还有很好的函数列表,可以在信号处理程序中使用(段落异步信号安全函数)。在你这样做之后,请告诉我们它是否有任何不同。
答案 1 :(得分: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
可能是巧合。 (但未定义的行为也是巧合!)
答案 2 :(得分:0)
我编译了这段代码(原始的微不足道的变体 - 添加了明确的void
参数列表,#define _XOPEN_SOURCE 700
来获取timer_t
声明,简化了信号处理程序,并链接和测试了带有-lrt
的Linux(RHEL 5),因为Mac OS X在timer_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()
运行的命令,实际上它们不应该。{/ p>
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;
}