进程通信之信号

目录

  • 信号的概念
  • 信号函数分析
  • 案例有两个

写在前面:下面注释有的有英文,并不是我翻译成英语的,是man文档的原句,后面的中文是我参考有关资料和自己分析的中文。

(一)信号的基本概念
  • 信号全称为软中断信号,也有人称作软中断。可以看出,它的实质和使用很像中断
  • 软中断信号( signal,又简称为信号)用来通知进程发生了异步事件,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
  • 三种处理行为:
第一种
类似中断的处理程序(a pointer to a signal handling function),对于需要处理的信号,进程可以指定处理函数,由该函数来处理。
第二种
忽略(SIG_IGN)某个信号,对该信号不做任何处理,就象未发生过一样。
第三种
对该信号的处理保留系统的默认值(SIG_DFL),这种缺省操作,对大部分的信号的缺省操作是使得进程终止。

在这里插入图片描述

  • 信号的分类–简单描述下
    在这里插入图片描述
    POSIX.1中提及的signal值(man 7 signal信息量很丰富,man手册要仔细阅读哦!!)。我保留英语,可以帮你快速理解。自己总结做成pdf的,找了好多资料。。。
    在这里插入图片描述
    注意:里面有好几个经常用到的
    SIGINT、SIGQUIT、SIGKILL、SIGALRM、SIGSTOP、SIGCHLD、SIGPIPE、等,总之,信号是异步的,在操作系统中很重要
    还有其他的信号就不用说了,如:SUSv2 。文档里有。。

等会有一个关于alarm例程:alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds—闹铃,和SIGALRM信号搭配使用,实现在设定闹铃时间发出信号

(二)信号操作流程

先介绍函数,涉及好多个。。 前面几个是比较重要的
(1)检查和更改信号操作

sigaction():examine and change a signal action
 int sigaction(int signum, const struct sigaction *act ,struct sigaction *oldact);

参数分析:

  • signum: 表示信号取值,就是上面的表的signal值。
  • act: If act is non-NULL, the new action for signal signum is installed from act. If oldact is non-NULL, the previous action is saved in oldact.
    如果act不空,新的act将存进,旧的act将存在oldact里

注意:这里涉及一个很重要的结构体
struct sigaction----描述信号到来所采取的动作

//Structure describing the action to be taken when a signal arrives.-描述信号到来所采取的动作 
struct sigaction {
  void     (*sa_handler)(int);							//SIG_DFL for the default action, SIG_IGN to ignore this signal, or a pointer to a signal handling function.
  void     (*sa_sigaction)(int, siginfo_t *, void *);	//do not assign to both sa_handler and sa_sigaction
  sigset_t   sa_mask;									//specifies a mask of signals which should be blocked
  int        sa_flags;//=0,如果系统调用被sig信号打断,则在处理完sig信号后,就会重新调用被打断的系统调用,这也是linux默认的行为。
  void     (*sa_restorer)(void);							//obsolete过时了,不要再使用了
};
  • (*sa_handler)(int) : 有三种行为,上面讲了哈!
  • (*sa_sigaction)(int, siginfo_t *, void *): do not assign to both sa_handler and sa_sigaction—就是结构体里面的前两个不要都赋值。为什么呢?其实在sigaction.h中定义了。
    位置 :/usr/include/bits/sigaction.h --里面还有其他参数,有兴趣可以仔细分析下,不然 man 2 sigaction看着有些吃力。
    在这里插入图片描述
  • sa_mask:specifies a mask of signals which should be blocked。你要屏蔽才有用哈
  • sa_flags:这个都够写一篇博客了,感兴趣网上自己找下资料
    在这里插入图片描述
  • (*sa_restorer)(void): 过时了,不要研究了。
  • 返回值: sigaction() returns 0 on success and -1 on error
    如:
    在这里插入图片描述

(2)设置屏蔽字

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
  • how:–有三个常量值
    SIG_BLOCK:The set of blocked signals is the union of the current set and the set argument.
    SIG_UNBLOCK:The signals in set are removed from the current set of blocked signals
    SIG_SETMASK:设置屏蔽字,将set中屏蔽字生效
    这里设置ctrl+c屏蔽字
  • 如果act不空,新的act将存进,旧的act将存在oldact里。act空,不做改变
  • 返回值: sigprocmask() returns 0 on success and -1 on error

(3)测试信号是否被屏蔽

int sigpending(sigset_t *set);
  • 返回值: sigpending() returns 0 on success and -1 on error

(4)测试是否加入信号集

int sigismember(const sigset_t *set, int signum);
  • signum: 表示信号取值,就是上面的表的signal值。
  • 返回值: 1 if signum is a member of set, 0 if signum is not a member, and -1 on error.
    在这里插入图片描述

(5)删除信号集中的信号

int sigdelset(sigset_t *set, int signum);
  • signum: 表示信号取值,就是上面的表的signal值。
  • 返回值: return 0 on success and -1 on error.

(6)取消对SIGINT的屏蔽

int sigsuspend(const sigset_t *mask);
  • 返回值: sigsuspend() always returns -1, normally with the error EINTR
    在这里插入图片描述

(7)清空信号集

//清空信号集
int sigemptyset(sigset_t *set);
  • set:信号集
  • 返回值: return 0 on success and -1 on error.

(8)添加信号集

//添加信号集
int sigaddset(sigset_t *set, int signum);
  • set:信号集
  • signum: 表示信号取值,就是上面的表的signal值。
  • 返回值: return 0 on success and -1 on error.

(8)休息等待信号的到来–和上面配合使用的

//causes the calling process(or thread)to sleep until a signal is delivered
 int pause(void);
  • 返回值: pause() only returns when a signal was caught and the signal-catching function returned. and -1 on error.
(三)案例一

闹铃:在正常延时7s的过程中,在第5s打印Hello world!!!(闹铃信号)

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

/****************************************************************************************
**									信号处理signal handling
** alarm():
**	 unsigned int alarm(unsigned int seconds);
** 描述:alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds
** 		 闹铃,和SIGALRM信号搭配使用,实现在设定闹铃时间发出信号
** RETURN VALUE
** 	 the number of seconds remaining
** signal():
**	sighandler_t signal(int signum, sighandler_t handler);
**  signum :等待的信号
**  handler:信号到来之后,触发的处理方式,如一个函数
** RETURN VALUE
** 	 成功返回0,错误返回-1
****************************************************************************************/


void handler()
{
	printf("Hello world!!!\n");
}

//实验现象:在正常延时7s的过程中,在第5s打印Hello world!!!
int main(void)
{
	int i = 1;
	
	signal(SIGALRM, handler);				//这里设置了一个闹钟,是在5s的时候运行handler函数,也就是打印Hello world!!!
	alarm(5);
	
	for(;i < 7; i++)
	{
		printf("Sleeping %d ...\n",i);
		sleep(1);
	}
}

输出:
在这里插入图片描述

案例二
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

/* //Structure describing the action to be taken when a signal arrives.-描述信号到来所采取的动作 
struct sigaction {
  void     (*sa_handler)(int);							//SIG_DFL for the default action, SIG_IGN to ignore this signal, or a pointer to a signal handling function.
  void     (*sa_sigaction)(int, siginfo_t *, void *);	//do not assign to both sa_handler and sa_sigaction
  sigset_t   sa_mask;									//specifies a mask of signals which should be blocked
  int        sa_flags;//=0,如果系统调用被sig信号打断,则在处理完sig信号后,就会重新调用被打断的系统调用,这也是linux默认的行为。
  void     (*sa_restorer)(void);							//obsolete过时了,不要再使用了
}; */

/****************************************************************************************
**									信号处理signal handling
** sigaction():examine and change a signal action
**	 int sigaction(int signum, const struct sigaction *act ,struct sigaction *oldact);
** act:
**  If act is non-NULL, the new action for signal signum is installed from act. If oldact is non-NULL, the previous action is saved in oldact.
	如果act不空,新的act将存进,旧的act将存在oldact里
** 描述:alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds
** 		 闹铃,和SIGALRM信号搭配使用,实现在设定闹铃时间发出信号
** RETURN VALUE
** 	 sigaction() returns 0 on success and -1 on error

** sigprocmask():
**	int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
** SIG_SETMASK:设置屏蔽字,将set中屏蔽字生效
** 如果act不空,新的act将存进,旧的act将存在oldact里。act空,不做改变
** RETURN VALUE
** 	sigprocmask() returns 0 on success and -1 on error.

** sigpending(): examine pending signals--测试SIGINT是否被屏蔽
**	 int sigpending(sigset_t *set);
** RETURN VALUE
** 	sigpending() returns 0 on success and -1 on error.

** sigemptyset():Clear all signals from SET.
**	 int sigemptyset(sigset_t *set);
** RETURN VALUE
**	 sigemptyset() return 0 on success and -1 on error.

** sigismember():测试是否加入信号集
**	 int sigismember(const sigset_t *set, int signum);
** RETURN VALUE
**	 1 if signum is a member of set, 0 if signum is not a member, and -1 on error.

** sigdelset():删除信号集中的信号
**	 int sigdelset(sigset_t *set, int signum);
** RETURN VALUE
**	 sigdelset() return 0 on success and -1 on error.

** sigaddset():set to full, including all signals-添加信号集
**	 int sigaddset(sigset_t *set, int signum);
** signum: 就是所有信号取值,上面的表
** RETURN VALUE
**	 sigaddset() return 0 on success and -1 on error.

** sigsuspend(): wait for a signal
**	 int sigsuspend(const sigset_t *mask);
** signum: 就是所有信号取值,上面的表
** RETURN VALUE
**	 sigaddset() return 0 on success and -1 on error.

** pause(): causes the calling process(or thread)to sleep until a signal is delivered
**	 int pause(void);
** RETURN VALUE
**	 pause() only returns when a signal was caught and the signal-catching function returned. and -1 on error.
****************************************************************************************/

//处理函数
void handler(int sig)
{
	printf("Handl signal is %d!!!\n",sig);
}

int main()
{
	sigset_t sigset;											//记录屏蔽字
	sigset_t ign;												//记录被阻塞的信号集
							
	struct sigaction act;
	
	//清空信号集
	sigemptyset(&sigset);
	sigemptyset(&ign);
	
	//添加信号集
	sigaddset(&sigset, SIGINT);									//SIGINT----CTRL+C
	
	//设置处理函数及信号集----给结构体赋值
	act.sa_handler = handler;									//处理函数
	sigemptyset(&act.sa_mask);									//设置屏蔽
	act.sa_flags = 0;											//默认行为,
	sigaction(SIGINT, &act, 0);
	
	printf("Wait the signal SIGINT!!!\n");
	pause();													//挂起进程,等待信号  
	
	//设置屏蔽字,SIGINT
	sigprocmask(SIG_SETMASK, &sigset, 0);						//将sigset的SIGINT生效
	printf("Please press ctrl+c in 5 seconds!!!\n");
	sleep(5);
	
	//测试SIGINT是否被屏蔽
	sigpending(&ign);
	
	//测试是否加入信号集
	if(sigismember(&ign, SIGINT))
	{
		printf("The SIGINT has ignored!!!\n");
	}
	
	//删除信号集中的信号
	sigdelset(&sigset, SIGINT);
	printf("Wait the signal SIGINT!!!\n");
	
	//取消对SIGINT的屏蔽
	sigsuspend(&sigset);
	printf("App exit after 5 seconds!!!\n");
	sleep(5);
	
	return 0;
}

**输出:**里面输出的2,是SIGINT的值。
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值