1.一段代码存在的问题

因为操作是不原子的

void Handler(int n)
{write(1, "!", 1);
}int main()
{int i;sigset_t set;sigemptyset(&set);sigaddset(&set, SIGINT);signal(SIGINT, Handler);while(1){///阻塞信号sigprocmask(SIG_BLOCK, &set, NULL);for(i = 0; i < 5; i++){write(1, "*", 1);sleep(1);}write(1, "\n", 1);//恢复信号sigprocmask(SIG_UNBLOCK, &set, NULL);//等待信号pause();}return 0;
}

我们要实现的功能是当一行的*打印完之后,我们按下ctrl+c,才能继续打印

上面图片中出现的问题,在信号阻塞的时候,如果产生了信号,该信号被推迟直到解除了阻塞,所以该信号就好像发生在恢复信号和等待信号之间。如果在解除阻塞时候和pause之间确实发生了信号,那么可能该信号永远不可见,使得pause永远阻塞。

2.sigsuspend

为了纠正此问题,需要在一个原子操作中实现 先恢复信号屏蔽字,然后进程休眠,如果捕捉到一个信号,而且从该信号处理程序返回,则该函数返回

void Handler(int n)
{write(1, "!", 1);
}int main()
{int i;sigset_t set, unblock_set;sigemptyset(&set);sigaddset(&set, SIGINT);signal(SIGINT, Handler);//先让不阻塞信号sigprocmask(SIG_UNBLOCK, &set, NULL);//把当前的状态保存到unblock_set中sigprocmask(SIG_BLOCK, &set, &unblock_set);while(1){sigprocmask(SIG_BLOCK, &set, NULL);for(i = 0; i < 5; i++){write(1, "*", 1);sleep(1);}write(1, "\n", 1);//sigprocmask(SIG_UNBLOCK, &set, NULL);//pause();//原子化操作 sigsuspend(&unblock_set);}return 0;
}

3.sigaction

signal在多个信号,共用一个信号处理函数的时候会产生问题
signal也不能区分信号的来源

NAMEsigaction - examine and change a signal actionSYNOPSIS#include <signal.h>int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
 The sigaction structure is defined as something like:struct sigaction {void     (*sa_handler)(int);//可以替换signal那个函数void     (*sa_sigaction)(int, siginfo_t *, void *);sigset_t   sa_mask;//信号集类型 可以把某些信号block住int        sa_flags;void     (*sa_restorer)(void);
};
sa_mask specifies a mask of signals which should be blocked

这里可以获得信号的属性

siginfo_t {int      si_signo;    /* Signal number */int      si_errno;    /* An errno value */int      si_code;     /* Signal code */int      si_trapno;   /* Trap number that causedhardware-generated signal(unused on most architectures) */pid_t    si_pid;      /* Sending process ID */uid_t    si_uid;      /* Real user ID of sending process */int      si_status;   /* Exit value or signal */clock_t  si_utime;    /* User time consumed */clock_t  si_stime;    /* System time consumed */sigval_t si_value;    /* Signal value */int      si_int;      /* POSIX.1b signal */void    *si_ptr;      /* POSIX.1b signal */int      si_overrun;  /* Timer overrun count; POSIX.1b timers */int      si_timerid;  /* Timer ID; POSIX.1b timers */void    *si_addr;     /* Memory location which caused fault */long     si_band;     /* Band event (was int inglibc 2.3.2 and earlier) */int      si_fd;       /* File descriptor */short    si_addr_lsb; /* Least significant bit of address(since Linux 2.6.32) */
}

4.一个简单的demo



以前写的一个令牌桶,来实行流量控制,现在用户态的一个ALRM信号,会干扰流量控制
解决


void AlarmAction(int nNum, siginfo_t *info, void *unuse)
{int i;//alarm(1);//printf("**********************\n");//只有内核态 才可以if(SI_KERNEL == info->si_code)for(i = 0; i < MYTBF_MAX; i++){if(NULL != job[i]){job[i]->token += job[i]->cps ;if(job[i]->burst < job[i]->token)job[i]->token = job[i]->burst;}}}void ModuleUnload(void)
{int i;struct itimerval itv;//signal(SIGALRM, SignalRes);//alarm(0);//对信号处理进行恢复sigaction(SIGALRM, &oldsa, NULL);//关闭alarmitv.it_interval.tv_sec = 0;itv.it_interval.tv_usec = 0;itv.it_value.tv_sec = 0;itv.it_value.tv_usec = 0;setitimer(ITIMER_REAL, &itv, NULL);for(i = 0; i < MYTBF_MAX; i++){free(job[i]);}}void ModuleLoad(void)
{//SignalRes = signal(SIGALRM, AlarmHandler);//alarm(1);//struct sigaction sa;struct itimerval itv;//设置信号处理函数sa.sa_sigaction = AlarmAction;//设置flag 使用那个三参的函数指针sa.sa_flags = SA_SIGINFO;//不需要屏蔽任何masksigemptyset(&sa.sa_mask);//指定信号sigaction(SIGALRM, &sa, &oldsa);//这个就是设置时间 自动形成一个alarm链条itv.it_interval.tv_sec = 1;itv.it_interval.tv_usec = 0;itv.it_value.tv_sec = 1;itv.it_value.tv_usec = 0;setitimer(ITIMER_REAL, &itv, NULL);Inited = 1;//钩子函数atexit(ModuleUnload);
}

代码的其余部分不变

sigsuspend/sigaction相关推荐

  1. linux下 如何用信号signal 终止或者暂停子线程,linux下实现线程暂停

    记得在windows下有一个SuspendThread使线程挂起的函数,却发现linux下没有类似的函数,于是想自己写个.. 刚开始就想到用信号(没办法,正在看auep,只能想到这个) test1: ...

  2. linux下实现线程暂停

    记得在windows下有一个SuspendThread使线程挂起的函数,却发现linux下没有类似的函数,于是想自己写个.. 刚开始就想到用信号(没办法,正在看auep,只能想到这个) test1: ...

  3. Linux信号控制-sigprocmask,sigsuspend,sigpending,sigaction,sigqueue

    写在前面:小生纯业余选手,开此博仅仅是为了积累,纯当笔记来用.如有看官光临小生博客,请不要相信我的代码就是正确的.如果您发现了错误也恳请耽误您一点时间,请您在下面指出来,不胜感激! 如果发现一些笔记的 ...

  4. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()...

    我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...

  5. sigsuspend sigprocmask函数的用法

    一个进程的信号屏蔽字规定了当前堵塞而不能递送给该进程的信号集.调用函数sigprocmask能够检測或更改其信号屏蔽字,或者在一个步骤中同一时候运行这两个操作. #include <signal ...

  6. sigaction函数学习

    sigaction(查询或设置信号处理方式) 相关函数 signal,sigprocmask() ,sigpending,sigsuspend, sigemptyset 表头文件 #include&l ...

  7. 2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

     1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL                                            默 ...

  8. Linux信号实现精确到微秒的sleep函数:通过sigsuspend函数解决时序竞态问题

    原理就是先使用定时器定时,然后再使用pause函数或者sigsuspend函数主动阻塞挂起,最终恢复现场. 如果使用pause函数的话,优点是使用简单,缺点是有可能产生时序竞态,导致进程一直阻塞下去: ...

  9. 函数sigsuspend

    1. 测试代码: #include<stdio.h> #include<stdlib.h> #include<signal.h> #include<errno ...

最新文章

  1. 7本书带你掌握数据科学中的数学基础(附下载)
  2. printf不能直接输出string类型
  3. c# winform 程序打包部署
  4. 慕课堂计算机word,数字技能 – 办公工具(Microsoft Word、Excel、Power Point)
  5. django 不包括字段 序列化器_手写一个Django序列化功能
  6. Windows环境下Code::Blocks中成功配置MySQL Connector/C连接MySQL数据库
  7. STM32F103_SPI读写外部FLASH
  8. 抖音ai智能机器人挂机_抖音上最火的人工智能机器人--LUKA绘本阅读机器人
  9. 简约、高质量简历模板
  10. 渐进式Express源码学习6-独孤求败
  11. java服务端用到的javase的基础知识_javase基础篇知识归纳
  12. ArcGIS必会的几个工具的应用
  13. 读论文,第十一天:Flexible Strain Sensors for Wearable Hand Gesture Recognition: From Devices to Systems
  14. UG NX 12抽取体特征
  15. Linux下运行jar包的方法
  16. 西安交警如何借力智能化科技手段开展城市交通“智”理?
  17. 实体知识+字典树辅助jieba的分词(并对三国演义进行简单分析)
  18. wss 协议php,作为ws/wss客户端
  19. 怎样在应用中实现自助报表功能
  20. phpcms实现PC网站接入微信Native支付

热门文章

  1. “人大附中翠微学校”要成立“小学部” vs 翠微小学
  2. 自由职客_全职工作时兼顾自由职业的14种方法
  3. 海汽集团:业财共享服务中心建设推进集团数字治理
  4. 『杭电1410』PK武林盟主
  5. 监控摄像头是如何追踪的?
  6. 用MQTT.fx检查发布和订阅的mqtt消息
  7. JavaWeb开发框架——SpringMVC
  8. sadasddddddd
  9. RT Master Mix for qPCR—高效反转录试剂
  10. controller返回数据