1.功能sigaction

sigaction动与指定信号相关联的处理动作。其函数原型例如以下:

#inlcude <signal.h>

int sigaction(int signo,const struct sigaction * restrict act,struct sigaction * restrict act);

当中參数signo是要检測或改动其详细动作的信号编号。

若act指针非空,则要改动其动作。假设oact指针非空。则系统经由oact指针返回该信号的上一个动作。结构体sigaction的结构例如以下:

一旦对给定的信号设置了一个动作,那么在调用signation显式的改变它之前,该设置就一直有效。

act结构的sa_flags字段指定对信号进行处理的各个选项。下图具体列出了这些选项的意义。

sigaction结构的sa_sigaction字段是一个替代的信号处理程序。

当sa_flags设置了SA_SIGINFO标志时,使用该信号处理程序。

通常,信号处理函数的形式是这种:void handler(int signo)。

但假设设置了SA_SIGINFO标志,则信号处理函数的原型是这种:void handler(int signo,siginfo_t *info,void
*context)。siginfo_t结构包括了信号产生原因的有关信息。

该结构的样式例如以下所看到的:

context參数是无类型指针。它可被强制类型转换为ucontext_t结构类型,该结构标识信号传递时的上下文信息。

2.函数sigsetjmp和siglongjmp

在信号处理程序中进行非局部转移时使用这两个函数。

#include <setjmp.h>

int sigsetjmp(sigjmp_buf env,int savemask);//若直接调用,返回0。若从siglongjmp调用返回,则返回非0。

void siglongjmp(sigjmp_buf env,int val);

在调用sigsetmask时。假设savemask值为1,则将进程当前的屏蔽字保存在env中。

调用siglongjmp时,假设带非0savemask的sigsetjmp调用已经将进程的屏蔽字保存在env中了。则siglongjmp从中恢复保存的信号屏蔽字。

例:

  1. #include "apue.h"
  2. #include <setjmp.h>
  3. #include <time.h>
  4.  
  5. static void sig_usr1(int);
  6. static void sig_alrm(int);
  7. static sigjmp_buf jmpbuf;
  8. static volatile sig_atomic_t canjump;
  9.  
  10. void pr_mask(const char *str)//打印当前被堵塞的信号
  11. {
  12. sigset_t sigset;
  13. int errno_save;
  14.  
  15. errno_save = errno; /* we can be called by signal handlers */
  16. if (sigprocmask(0, NULL, &sigset) < 0)
  17. perror("sigprocmask error");
  18.  
  19. printf("mask: %s", str);
  20. if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
  21. if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
  22. if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
  23. if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
  24. if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
  25.  
  26. /* remaining signals can go here */
  27.  
  28. printf("\n");
  29. errno = errno_save;
  30. }
  31.  
  32. Sigfunc * signal(int signo,Sigfunc * func)
  33. {
  34. struct sigaction act,oact;
  35. act.sa_handler = func;
  36. sigemptyset(&act.sa_mask);
  37. act.sa_flags = 0;
  38. if(signo == SIGALRM) {
  39. #ifdef SA_INTERRUPT
  40. act.sa_flags |= SA_INTERRUPT;
  41. #endif
  42. } else {
  43. act.sa_flags |= SA_RESTART;
  44. }
  45. if(sigaction(signo,&act,&oact) < 0)
  46. return (SIG_ERR);
  47. return (oact.sa_handler);
  48. }
  49.  
  50. int main(void)
  51. {
  52. if(signal(SIGUSR1,sig_usr1) == SIG_ERR)
  53. err_sys("signal(SIGUSR1) error");
  54.  
  55. if(signal(SIGALRM,sig_alrm) == SIG_ERR)
  56. err_sys("signal(SIGALRM) error");
  57.  
  58. pr_mask("starting main:");
  59.  
  60. if(sigsetjmp(jmpbuf,1)) {
  61. pr_mask("ending main:");
  62. exit(0);
  63. }
  64. canjump = 1;
  65. for(;;)
  66. pause();
  67. }
  68.  
  69. static void sig_usr1(int signo)
  70. {
  71. time_t starttime;
  72.  
  73. if(canjump == 0)
  74. return;
  75.  
  76. pr_mask("starting sig_usr1:");
  77.  
  78. alarm(3);
  79. starttime = time(NULL);
  80. for(;;)
  81. if(time(NULL) > starttime+5)
  82. break;
  83. pr_mask("finishing sig_usr1:");
  84. canjump = 0;
  85. siglongjmp(jmpbuf,1);
  86. }
  87.  
  88. static void sig_alrm(int signo)
  89. {
  90. pr_mask("in sig_alrm:");
  91. }

3.函数sigsuspend

#include <signal.h>

int sigsuspend(const sigset_t * sigmask);

进程的信号屏蔽字设置由sigmask指定。

在捕捉到一个信号前,该进程被挂起。假设捕捉到一个信号,则sigsuspend返回,而且该进程的新高屏蔽字设置为曾经的值。

例:

  1. #include "apue.h"
  2.  
  3. static void sig_int(int);
  4.  
  5. void pr_mask(const char *str)//打印当前被堵塞的信号
  6. {
  7. sigset_t sigset;
  8. int errno_save;
  9.  
  10. errno_save = errno; /* we can be called by signal handlers */
  11. if (sigprocmask(0, NULL, &sigset) < 0)
  12. perror("sigprocmask error");
  13.  
  14. printf("mask: %s", str);
  15. if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
  16. if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
  17. if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
  18. if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
  19. if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
  20.  
  21. /* remaining signals can go here */
  22.  
  23. printf("\n");
  24. errno = errno_save;
  25. }
  26.  
  27. Sigfunc * signal(int signo,Sigfunc * func)
  28. {
  29. struct sigaction act,oact;
  30. act.sa_handler = func;
  31. sigemptyset(&act.sa_mask);
  32. act.sa_flags = 0;
  33. if(signo == SIGALRM) {
  34. #ifdef SA_INTERRUPT
  35. act.sa_flags |= SA_INTERRUPT;
  36. #endif
  37. } else {
  38. act.sa_flags |= SA_RESTART;
  39. }
  40. if(sigaction(signo,&act,&oact) < 0)
  41. return (SIG_ERR);
  42. return (oact.sa_handler);
  43. }
  44.  
  45. int main(void)
  46. {
  47. sigset_t newmask,oldmask,waitmask;
  48.  
  49. pr_mask("program start:");
  50.  
  51. if(signal(SIGINT,sig_int) == SIG_ERR)
  52. err_sys("signal(SIGINT) error");
  53. sigemptyset(&waitmask);
  54. sigaddset(&waitmask,SIGUSR1);
  55. sigemptyset(&newmask);
  56. sigaddset(&newmask,SIGINT);
  57.  
  58. if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)
  59. err_sys("SIG_BLOCK error");
  60.  
  61. pr_mask("in critical region:");
  62.  
  63. if(sigsuspend(&waitmask) != -1)
  64. err_sys("suspend error");
  65.  
  66. pr_mask("after return from sigsuspend:");
  67.  
  68. if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)
  69. err_sys("SIG_SETMASK error");
  70.  
  71. pr_mask("program end:");
  72. }
  73.  
  74. static void sig_int(int signo)
  75. {
  76. pr_mask("in sig_int:");
  77. }

4.函数sigqueue

使用排队信号必须做一下几个操作:

(1)使用sigaction函数安装信号处理程序时指定SA_SIGINFO标志。

(2)在sigaction结构的sa_sigaction成员中提供信号处理程序。

(3)使用sigqueue函数发送信号。

#include <signal.h>

int sigqueue(pid_t pid,int signo,const union sigval value);

5.信号名和编号

能够通过psignal函数可移植地打印与信号编号相应的字符串。

#include <signal.h>

void psignal(int signal,const char * msg);//字符串msg输入到标准错误流

假设只需要字符信号的叙述性说明,可以用于strsignal功能。

#include <string.h>

char *strsignal(int signo);

《UNIX级别编程环境》注意读出信号(2)的更多相关文章

  1. 记录一次配置unix网络编程环境的过程和遇到的问题

    记录一次搭建unix网络编程环境过程中遇到的问题和总结 计算机环境虚拟机 linuxmint-18-xfce-64bit 1.打开unix网络编程.iso 把目录下的文件复制到某一目录,修改权限,可命 ...

  2. unix网络编程环境搭建

    unix网络编程环境搭建 网络编程 环境 1.点击下载源代码 可以通过下列官网中的源代码目录下载最新代码: http://www.unpbook.com/src.html 2.解压文件 tar -xz ...

  3. UNIX网络编程 环境搭建

    配置好动态链接库或者静态链接库 1,下载UNIX网络编程书的头文件及示例源码unpv13e 2    按照readme来编译 Execute the following from the src/ d ...

  4. Unix系统编程()改变信号处置:signal

    Unix系统提供了两种方法来改变信号处置:signal和sigaction.这篇描述的是signal系统调用,是设置信号处理的原始API,所提供的接口比sigaction简单.另一方面,sigacti ...

  5. Unix系统编程()发送信号的其他方式:raise和killpg

    有时,进程需要向自身发送信号,raise 函数就执行了这一任务. #include <signal.h> int raise(int sig); 在单线程程序中,调用raise相当于对ki ...

  6. Unix系统编程()发送信号kill

    与shell的kill命令类似,一个进程能够使用kill系统调用向另一进程发送信号. 之所以选择kill作为术语,因为早期UNIX实现中大多数信号的默认行为是终止进程. #include <si ...

  7. ubuntu14.04下unix网络编程环境的配置

    建议 unpv13e/README看一下,忽略一下内容 ===================================================================== 操作 ...

  8. unix网络编程环境配置程序运行

    1 查看ubuntu版本 cat /etc/issue 2 查看版本 cat /proc/version 3 下载 你可以通过其他方式下载 这里下载好了 文件名为unpv13e 4 开始配置 (1)c ...

  9. ubuntu14.04下unix网络编程 环境的配置

    在ubuntu下 首先:在unpv13e文件加下 ./configure cd lib make cd ../libfree make cd ../liggai make cd .. vim lib/ ...

随机推荐

  1. 第1周 SQL Server 如何执行一个查询

    原文:第1周 SQL Server 如何执行一个查询 大家好,欢迎来到第1周的SQL Server性能调优培训.在我们进入SQL Server性能调优里枯燥难懂的细节内容之前,我想通过讲解SQL Se ...

  2. 学习FFmpeg API – 解码视频

    本文转载 视频播放过程 首先简单介绍以下视频文件的相关知识.我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的 ...

  3. 使用ZeroMQ(clrzmq)实现异步通信

    ZeroMQ是对Socket的封装,通过组合多种类型的结点可以实现复杂的网络通信模式.而且ZeroMQ设计简单,可以有多种平台实现,对于跨平台项目是一个福音. clrzmq是ZeroMQ的C#语言的实 ...

  4. 【设计模式】Template Method模式

    OO基金会 封装 多态 继承 OO原则 封装变化 多用组合,少用继承 针对接口编程.不针对实现编程 为交互对象的松耦合设计而努力 类应该对扩展开放,对改动关闭 依赖抽象,不要依赖详细类 仅仅和朋友交谈 ...

  5. python K-means工具包初解

    近期数据挖掘实验,写个K-means算法,写完也不是非常难,写的过程中想到python肯定有包,尽管师兄说不让用,只是自己也写完了,而用包的话,还不是非常熟,略微查找了下资料,学了下.另外,自己本身写 ...

  6. 使用order by和rownum时特别注意

    起因 在项目中有用到某表作为数据来源,在页面以列表的形式显示.使用的数据库是Oracle,分页的时候使用到了rownum这个关键字.列表有排序功能,自然也用到了order by.接下来问题出现了,我在 ...

  7. JAVA字符串比较equals()和equalsIgnoreCase()差异

    .用equals( )方法比較两个字符串是否相等.它具有例如以下的一般形式: boolean equals(Object str) 这里str是一个用来与调用字符串(String)对象做比較的字符串( ...

  8. DataGridView显示数据的两种方法

    1.简介 DataGridView空间是我们经常使用的显示数据的控件,它有极高的可配置性和可扩展性. 2.显示数据 DataGridView显示数据一般我们经常使用的有两种方法,一种是直接设置Data ...

  9. POJ 3177 Redundant Paths - from lanshui_Yang

    Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...

  10. C#启动进程之Process

    在程序设计中,我们经常会遇到要从当前的程序跳到另一个程序的设计需求.也就是当前进程创建另一个进程.C#提供了Process使得我们很方便的实现. 1.Process基本属性和方法 Id //进程的Id ...