《UNIX级别编程环境》注意读出信号(2)
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从中恢复保存的信号屏蔽字。
例:
#include "apue.h"
#include <setjmp.h>
#include <time.h> static void sig_usr1(int);
static void sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump; void pr_mask(const char *str)//打印当前被堵塞的信号
{
sigset_t sigset;
int errno_save; errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
perror("sigprocmask error"); printf("mask: %s", str);
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM "); /* remaining signals can go here */ printf("\n");
errno = errno_save;
} Sigfunc * signal(int signo,Sigfunc * func)
{
struct sigaction act,oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
} else {
act.sa_flags |= SA_RESTART;
}
if(sigaction(signo,&act,&oact) < 0)
return (SIG_ERR);
return (oact.sa_handler);
} int main(void)
{
if(signal(SIGUSR1,sig_usr1) == SIG_ERR)
err_sys("signal(SIGUSR1) error"); if(signal(SIGALRM,sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error"); pr_mask("starting main:"); if(sigsetjmp(jmpbuf,1)) {
pr_mask("ending main:");
exit(0);
}
canjump = 1;
for(;;)
pause();
} static void sig_usr1(int signo)
{
time_t starttime; if(canjump == 0)
return; pr_mask("starting sig_usr1:"); alarm(3);
starttime = time(NULL);
for(;;)
if(time(NULL) > starttime+5)
break;
pr_mask("finishing sig_usr1:");
canjump = 0;
siglongjmp(jmpbuf,1);
} static void sig_alrm(int signo)
{
pr_mask("in sig_alrm:");
}
3.函数sigsuspend
#include <signal.h>
int sigsuspend(const sigset_t * sigmask);
进程的信号屏蔽字设置由sigmask指定。
在捕捉到一个信号前,该进程被挂起。假设捕捉到一个信号,则sigsuspend返回,而且该进程的新高屏蔽字设置为曾经的值。
例:
#include "apue.h" static void sig_int(int); void pr_mask(const char *str)//打印当前被堵塞的信号
{
sigset_t sigset;
int errno_save; errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
perror("sigprocmask error"); printf("mask: %s", str);
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM "); /* remaining signals can go here */ printf("\n");
errno = errno_save;
} Sigfunc * signal(int signo,Sigfunc * func)
{
struct sigaction act,oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
} else {
act.sa_flags |= SA_RESTART;
}
if(sigaction(signo,&act,&oact) < 0)
return (SIG_ERR);
return (oact.sa_handler);
} int main(void)
{
sigset_t newmask,oldmask,waitmask; pr_mask("program start:"); if(signal(SIGINT,sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
sigemptyset(&waitmask);
sigaddset(&waitmask,SIGUSR1);
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT); if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)
err_sys("SIG_BLOCK error"); pr_mask("in critical region:"); if(sigsuspend(&waitmask) != -1)
err_sys("suspend error"); pr_mask("after return from sigsuspend:"); if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)
err_sys("SIG_SETMASK error"); pr_mask("program end:");
} static void sig_int(int signo)
{
pr_mask("in sig_int:");
}
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)的更多相关文章
- 记录一次配置unix网络编程环境的过程和遇到的问题
记录一次搭建unix网络编程环境过程中遇到的问题和总结 计算机环境虚拟机 linuxmint-18-xfce-64bit 1.打开unix网络编程.iso 把目录下的文件复制到某一目录,修改权限,可命 ...
- unix网络编程环境搭建
unix网络编程环境搭建 网络编程 环境 1.点击下载源代码 可以通过下列官网中的源代码目录下载最新代码: http://www.unpbook.com/src.html 2.解压文件 tar -xz ...
- UNIX网络编程 环境搭建
配置好动态链接库或者静态链接库 1,下载UNIX网络编程书的头文件及示例源码unpv13e 2 按照readme来编译 Execute the following from the src/ d ...
- Unix系统编程()改变信号处置:signal
Unix系统提供了两种方法来改变信号处置:signal和sigaction.这篇描述的是signal系统调用,是设置信号处理的原始API,所提供的接口比sigaction简单.另一方面,sigacti ...
- Unix系统编程()发送信号的其他方式:raise和killpg
有时,进程需要向自身发送信号,raise 函数就执行了这一任务. #include <signal.h> int raise(int sig); 在单线程程序中,调用raise相当于对ki ...
- Unix系统编程()发送信号kill
与shell的kill命令类似,一个进程能够使用kill系统调用向另一进程发送信号. 之所以选择kill作为术语,因为早期UNIX实现中大多数信号的默认行为是终止进程. #include <si ...
- ubuntu14.04下unix网络编程环境的配置
建议 unpv13e/README看一下,忽略一下内容 ===================================================================== 操作 ...
- unix网络编程环境配置程序运行
1 查看ubuntu版本 cat /etc/issue 2 查看版本 cat /proc/version 3 下载 你可以通过其他方式下载 这里下载好了 文件名为unpv13e 4 开始配置 (1)c ...
- ubuntu14.04下unix网络编程 环境的配置
在ubuntu下 首先:在unpv13e文件加下 ./configure cd lib make cd ../libfree make cd ../liggai make cd .. vim lib/ ...
随机推荐
- 程序设计实践C++ 程序代写(QQ 928900200)
程序设计实践 采用C++作为编程语言. 设计开发一个“学生信息”管理系统.该系统模拟数据库管理系统(DBMS)的功能,为用户提供数据存储.查找的能力. 该系统存储的学生信息包括: 学号.姓名.性别.语 ...
- 【hadoop之翊】——基于CentOS的hadoop2.4.0伪分布安装配置
今天总算是把hadoop2.4的整个开发环境弄好了,包括 windows7上eclipse连接hadoop,eclipse的配置和測试弄得烦躁的一逗比了~ 先上一张成功的图片,hadoop的伪分布式安 ...
- fork与vfork详解
一.fork函数 要创建一个进程,最基本的系统调用是fork,系统调用fork用于派生一个进程,函数原型如下: pid_t fork(void) 若成功,父进程中返回子进程ID,子进程中返回0,若出 ...
- swing中几种layout示例(转)
import java.awt.BorderLayout;import java.awt.FlowLayout;import java.awt.GridLayout;import java.awt.e ...
- Codeforces 385B Bear and Strings
题目链接:Codeforces 385B Bear and Strings 记录下每一个bear的起始位置和终止位置,然后扫一遍记录下来的结构体数组,过程中用一个变量记录上一个扫过的位置,用来去重. ...
- 表的顺序结构---重写Arraylist类
重写ArrayList类,为防止冲突,重写为MyArrayList,未继承Iterable类. public class MyArrayList<AnyType>{ int N=10; A ...
- base 64 编解码器
base 64 编解码 1. base64的编码都是按字符串长度,以每3个8bit的字符为一组, 2. 然后针对每组.首先获取每一个字符的ASCII编码. 3. 然后将ASCII编码转换成8bit的二 ...
- 构建安全的Xml Web Service系列之如何察看SoapMessage
原文:构建安全的Xml Web Service系列之如何察看SoapMessage 上一篇文章地址:构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53) ...
- ASP.NET自定义控件组件开发 第五章 模板控件开发
原文:ASP.NET自定义控件组件开发 第五章 模板控件开发 第五章 模板控件开发 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...
- ruby简单的基本 3
类 Ruby一切都是对象,它包含了一个恒定.例如,可以使用.class物业查看对象的类型,你可以看一下1.class.你会发现常1类型是Fixnum,1但它是Fixnum的一个例子. Ruby本类cl ...