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. 欧拉函数的求法(线性筛法?)
  2. 用Swift实现一款天气预报APP(三)
  3. SQL2000 好书 《SQL Server 2000数据库管理与开发技术大全》----求是科技 人民邮电出版社
  4. 【ZooKeeper Notes 15】Watcher使用的注意事项
  5. Chrome 浏览器降级后浏览网站不保留用户数据问题原因及解决方法
  6. Spring2.5整合JPA
  7. mongodb单机部署
  8. popfd指令_2. PUSH 和 POP 指 令 3
  9. java 检测表情符号_java – 检测String中的字符是否是表情符号(使用Android)
  10. 用EasyRecovery怎么恢复电脑中已删除的视频
  11. 如何:使用 DataAnnotations 特性验证模型数据+MetadataType的使用,MVC的Model层数据验证 指定要与数据模型类关联的元数据类
  12. 2021.09.22数字货币小计
  13. python测试app性能_pythonapp性能测试
  14. ttyS 和 ttyO 的区别
  15. GIS定位和自定义图标
  16. 美国签证(B1)经验总结
  17. MAT400安全帽标签
  18. IPMITOOL常用操作指令
  19. CentOS 6.9安装Python2.7.13
  20. 《微机原理与接口技术》复习参考资料,期末考试和专接本适用

热门文章

  1. 基于 Redis Stream 的消息队列
  2. Unity3D教程:抓取物件脚本、变数、名称
  3. oracle opidrv,华创信科oracle培训:数据库ORA-600[kcbchg1_6]解决
  4. 前端工程师,Es6面试题?promise概念?
  5. .NET 跨平台框架Avalonia UI: 填坑指北(二):在Linux上跑起来了
  6. 基于STM32F103C8T6的0.96寸OLED显示屏显示数据
  7. 【Unity入门】4.FBX模型和资源打包
  8. css-点击按钮实现水滴动画
  9. 微信小程序的 reLaunch , navigateTo ,navigateTo , switchTab ,navigateBack
  10. unity摄影机depth模式_摄像机的深度图