《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);

时间: 2024-10-20 06:51:44

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

unix网络编程环境搭建

unix网络编程环境搭建 新建 模板 小书匠 1.点击下载源代码 可以通过下列官网中的源代码目录下载最新代码: http://www.unpbook.com/src.html 2.解压文件 tar -xzvf upv13e.tar.gz 3.上传至阿里云 本人本地已经配置好,这次实验是将环境搭建至云服务器中. scp -r unpv13e [email protected]120.76.140.119:/root/program/unp // -r 上传文件夹  4.编译文件 cd unpv13

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

记录一次搭建unix网络编程环境过程中遇到的问题和总结 计算机环境虚拟机 linuxmint-18-xfce-64bit 1.打开unix网络编程.iso 把目录下的文件夹复制到某一目录,修改权限,可命令可鼠标操作. 2. [email protected] ~/unix/unpv13e $ sudo su [sudo] s 的密码: ss-Linux unpv13e # ./configure checking build system type... x86_64-unknown-linux

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

在ubuntu下 首先:在unpv13e文件加下 ./configure cd lib make cd ../libfree make cd ../liggai make cd .. vim lib/nup.h // 改动 #include "../config.h" 为 #include "config.h" / 拷贝头文件 sudo cp config.h /usr/local/include sudo cp lib/unp.h /usr/local/inclu

unix网络编程各种TCP客户-服务器程序设计实例附环境搭建和编译方法(一)

一,到http://download.csdn.net/detail/ts173383201/4505201去下载源代码,然后解压: 二,cd到你解压后的文件夹下,就是有configure的那个目录下,执行命令./configure: 三,执行cd lib跳到lib目录下,执行make命令,会在上层目录(就是刚才有configure那个目录)生成libunp.a文件 四,复制这个静态库libunp.a到/usr/lib/和/usr/lib64/中; 五,接下来在目录中找到unp.h和config

Unix NetWork Programming(unix环境编程)——环境搭建(解决unp.h等源码编译问题)

此配置实例亲测成功,共勉,有问题大家留言. 环境:VMware 10 + unbuntu 14.04 为了unix进行网络编程,编程第一个unix程序时遇到的问题,不能包含unp.h文件,这个感觉和apue.h差不多,不过这里需要编译源代码,为了以后方便,现在整理如下: 主要有两点一是生成libunp.a这个库,二是得到unp.h.config.h这两个个头文件. 1,安装编译器,为了齐全还是安装一下build-essential sudo apt-get install build-essen

&lt;unix网络编程&gt; 的环境配置

首先在网上下载UNP的库文件,然后就可以安装学了.我的系统环境: 2.6.32-131.0.15.el6.i686 #1 SMP Sat Nov 12 17:30:50 CST 2011 i686 i686 i386 GNU/Linux LSB Version:    :base-4.0-ia32:base-4.0-noarch:core-4.0-ia32:core-4.0-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia3

终端控制和和信号——《Unix/Linux编程实践教程》读书笔记(第6章)

1.有些程序处理从特定设备来的数据.这些与特定设备相关的程序必须控制与设备的连接.Unix系统中最常见的设备是终端. 2.终端驱动程序有很多设置.各个设置的特定值决定了终端驱动程序的模式.为用户编写的程序通常需要设置终端驱动程序为特定的模式. 3.键盘输入分为3类,终端驱动程序对这些输入做不同的处理.大多数建代表常规数据,它们从驱动程序传输到程序.有些键调用驱动程序中的编辑函数.如果按下删除键,驱动程序将前一个字符从它的行缓冲中删除,并将命令发送到终端屏幕,使之从显示器中删除字符.最后,有些键调

Unix网络编程之环境搭建

环境搭建 在尝试UNP书上的例子时,会因为找不到"unp.h"等问题无法编译成功,因此在学习之前需要先搭建好编译环境. 步骤 <1>下载  UNIX网络编程源代码unpv13e.tar.gz 下载链接  http://download.csdn.net/detail/ymsdu2004/4906181 <2>解压 进入该目录后执行 ./configure 再进入lib目录下 cd lib       执行 make 此时会在上层目录(就是刚才有configure

UNIX网络编程之旅-配置unp.h头文件环境

最近在学习Unix网络编程(UNP),书中steven在处理网络编程时只用了一个#include “unp.h”  相当有个性并且也很便捷 于是我把第三版的源代码编译实现了这个过程,算是一种个性化的开发环境的搭建吧,顺便把过程记录下来,以便自己以后查阅. 首先去网上找到源代码包unpv.13e.tar.gz 一找一大堆 解压缩到你的某个目录,unpv13e里面大致有这些目录 ├── aclocal.m4 ├── advio ├── bcast ├── config.guess ├── confi