C 如何使用信号来打印每个特定的时间并生成键盘中断?
我有下面的程序,我想使用信号每5秒打印一次,并处理键盘中断,如ctrl+c终止进程,ctrl+p打印结果C 如何使用信号来打印每个特定的时间并生成键盘中断?,c,signals,C,Signals,我有下面的程序,我想使用信号每5秒打印一次,并处理键盘中断,如ctrl+c终止进程,ctrl+p打印结果 int i=1; while(i>0) { i++; if(i%2==0) { printf("%d \n",i) } } 根据我的经验,信号处理很难可靠地完成,容易受到微妙的竞争条件等因素的影响(认为EINTR是个好主意的人应该被枪毙。)然后我想我从来没有真正掌握过UNIX的处理方式 我的建议是尽可能少地在处理程序内部进行工作,并尽量在你不直接感兴趣的地方
int i=1;
while(i>0)
{
i++;
if(i%2==0)
{
printf("%d \n",i)
}
}
根据我的经验,信号处理很难可靠地完成,容易受到微妙的竞争条件等因素的影响(认为EINTR是个好主意的人应该被枪毙。)然后我想我从来没有真正掌握过UNIX的处理方式 我的建议是尽可能少地在处理程序内部进行工作,并尽量在你不直接感兴趣的地方屏蔽信号 以下是我尝试安装SIGALRM处理程序并每5秒打印一条消息的过程:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/select.h>
// Raise a flag once the event occurs
volatile sig_atomic_t event;
void handler(int sig) { event = 1; }
int main(void) {
sigset_t mask;
// Install our alarm handler
struct sigaction action = { 0 };
action.sa_handler = handler;
sigaction(SIGALRM, &action, NULL);
// Mask out the alarm signal during normal operation to avoid races
// and having to handle EINTR everywhere
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_SETMASK, &mask, &mask);
// Here goes the main loop..
for(;;) {
// Set the alarm
alarm(5);
// Wait for the alarm to happen with the alarm signal unblocked.
// Add whatever other I/O you're waiting for here
pselect(0, NULL, NULL, NULL, NULL, &mask);
// Did we get woken up by an alarm signal?
if(event) {
event = 0;
puts("Alarm!");
}
}
}
#包括
#包括
#包括
#包括
//事件发生后立即升起标志
易失性信号原子事件;
无效处理程序(int sig){event=1;}
内部主(空){
sigset_t掩模;
//安装我们的警报处理器
struct sigaction action={0};
action.sa_handler=处理程序;
sigaction(SIGALRM,&action,NULL);
//在正常运行期间屏蔽报警信号,以避免冲突
//到处都要处理EINTR
sigpemptyset(&mask);
sigaddset(&mask,SIGALRM);
sigprocmask(SIG_设置掩码、掩码和掩码);
//主回路来了。。
对于(;;){
//设置警报
警报(5);
//在报警信号未被阻塞的情况下,等待报警发生。
//添加您在此等待的任何其他I/O
pselect(0、NULL、NULL、NULL、NULL和掩码);
//我们被警报信号吵醒了吗?
如果(事件){
事件=0;
放(“警报!”);
}
}
}
在您特定的计算绑定情况下,我建议策略性地从循环中轮询事件标志,而不是尝试从信号处理程序中提取和打印当前编号 如果您决定采用后一种方法,那么请注意,您不能依赖于能够以原子方式读取和写入值。相反,我建议采用双缓冲方案,将最近的两个值放在循环缓冲区中,并使用(volatile sig_atomic_t)索引指出正确的插槽。哦,您必须通过手动字符串操作和write()进行I/O,因为在信号处理程序中禁止printf。然而,真正的问题是,您将无法以任何正常的方式与其他标准输出文本同步
本质上,将多线程与单独的计算线程结合使用是实现相同目的的一种非常优越的方法。根据我的经验,信号处理很难可靠地完成,容易出现微妙的竞争条件等(任何认为EINTR是个好主意的人都应该被枪毙。)再说一次,我想我从来没有真正掌握过UNIX的做事方式 我的建议是尽可能少地在处理程序内部进行工作,并尽量在你不直接感兴趣的地方屏蔽信号 以下是我尝试安装SIGALRM处理程序并每5秒打印一条消息的过程:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/select.h>
// Raise a flag once the event occurs
volatile sig_atomic_t event;
void handler(int sig) { event = 1; }
int main(void) {
sigset_t mask;
// Install our alarm handler
struct sigaction action = { 0 };
action.sa_handler = handler;
sigaction(SIGALRM, &action, NULL);
// Mask out the alarm signal during normal operation to avoid races
// and having to handle EINTR everywhere
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_SETMASK, &mask, &mask);
// Here goes the main loop..
for(;;) {
// Set the alarm
alarm(5);
// Wait for the alarm to happen with the alarm signal unblocked.
// Add whatever other I/O you're waiting for here
pselect(0, NULL, NULL, NULL, NULL, &mask);
// Did we get woken up by an alarm signal?
if(event) {
event = 0;
puts("Alarm!");
}
}
}
#包括
#包括
#包括
#包括
//事件发生后立即升起标志
易失性信号原子事件;
无效处理程序(int sig){event=1;}
内部主(空){
sigset_t掩模;
//安装我们的警报处理器
struct sigaction action={0};
action.sa_handler=处理程序;
sigaction(SIGALRM,&action,NULL);
//在正常运行期间屏蔽报警信号,以避免冲突
//到处都要处理EINTR
sigpemptyset(&mask);
sigaddset(&mask,SIGALRM);
sigprocmask(SIG_设置掩码、掩码和掩码);
//主回路来了。。
对于(;;){
//设置警报
警报(5);
//在报警信号未被阻塞的情况下,等待报警发生。
//添加您在此等待的任何其他I/O
pselect(0、NULL、NULL、NULL、NULL和掩码);
//我们被警报信号吵醒了吗?
如果(事件){
事件=0;
放(“警报!”);
}
}
}
在您特定的计算绑定情况下,我建议策略性地从循环中轮询事件标志,而不是尝试从信号处理程序中提取和打印当前编号 如果您决定采用后一种方法,那么请注意,您不能依赖于能够以原子方式读取和写入值。相反,我建议采用双缓冲方案,将最近的两个值放在循环缓冲区中,并使用(volatile sig_atomic_t)索引指出正确的插槽。哦,您必须通过手动字符串操作和write()进行I/O,因为在信号处理程序中禁止printf。然而,真正的问题是,您将无法以任何正常的方式与其他标准输出文本同步
本质上,将多线程与单独的计算线程一起使用是实现相同目的的一种非常优越的方法。在哪个操作系统上?C标准不知道信号(除了使用
raise
)…使用sleep(5)
有什么问题?这是Linux操作系统我正在研究信号,所以我不能使用sleep,我必须使用信号。在哪个操作系统上?C标准不知道信号(除了使用raise
)…使用sleep(5)
有什么问题?这是Linux操作系统我正在研究信号,所以我不能使用sleep,我必须使用信号。