Linux系统编程笔记(06)

信号共性:
	简单、不能携带大量信息、满足条件才发送。
	
信号的特质:
	信号是软件层面上的“中断”。一旦信号产生,无论程序执行到什么位置,必须立即停止运行,处理信号,处理结束,再继续执行后续指令。
	所有信号的产生及处理全部都是由【内核】完成的。

信号相关的概念:
	产生信号:
		1. 按键产生
		2. 系统调用产生
		3. 软件条件产生
		4. 硬件异常产生
		5. 命令产生
	概念:
		未决:产生与递达之间状态。  
		递达:产生并且送达到进程。直接被内核处理掉。
		信号处理方式: 执行默认处理动作、忽略、捕捉(自定义)

		阻塞信号集(信号屏蔽字): 本质是位图。用来记录信号的屏蔽状态。一旦被屏蔽的信号,在解除屏蔽前,一直处于未决态。
		未决信号集:本质是位图。用来记录信号的处理状态。该信号集中的信号,表示,已经产生,但尚未被处理。

信号4要素:
	信号使用之前,应先确定其4要素,然后再用!!!
	编号、名称、对应事件、默认处理动作。可用 man 7 signal 查看帮助文档

	SIGHUP  默认动作:终止进程。关闭终端窗口时,内核向这个终端运行的每一个进程都发送这个信号
	SIGINT  默认动作:终止终端正在运行的程序,就是ctrl+C 
	SIGQUIT 默认动作:终止进程,就是ctrl+\
	SIGILL  默认动作:CPU检查某进程执行了非法指令,终止进程并产生core文件
	SIGTRAP 
	SIGABRT
	SIGBUS  总线错误,非法访问内存地址,包括内存对齐出错
	SIGFPE  除0操作
	SIGKILL 无条件终止进程,不能被忽略,不能被捕捉,只能执行信号。kill函数和kill命令
	SIGUSE1 自定义
	SIGSEGV 进程进行了无效内存访问(段错误)
	SIGUSE2 自定义
	SIGPIPE 
	SIGALRM
	SIGTERM
	SIGSTKFLT
	SIGCHLD
	SIGCONT
	SIGSTOP 无条件暂停进程,不能被忽略,不能被捕捉,只能执行信号
	SIGTSTP 暂停进程,ctrl+z
	SIGTTIN
	SIGTTOU
	SIGURG
	SIGXCPU
	SIGXFSZ
	SIGVTALRM
	SIGPROF

kill命令,产生信号,发给指定进程
	kill -9 pid //发送编号为9的信号,pid进程就会被杀死
	kill -11 pid //发送编号为11的信号,pid进程就会段错误
kill函数,产生信号,发给指定进程
#include <signal.h>
	int kill(pid_t pid, int signum)
	参数:
		pid: > 0:发送信号给指定进程
			= 0:发送信号给跟调用kill函数的那个进程处于同一进程组的进程。
			< -1: 取绝对值,发送信号给该绝对值所对应的进程组的所有组员。
			= -1:发送信号给,有权限发送的所有进程。
		signum:待发送的信号。尽量写信号名,不要写信号编号,因为不同芯片的操作系统信号编号可能不一样。
	返回值:
		成功: 0
		失败: -1 errno

进程组:每个进程都属于一个进程组,进程组是一个或多个进程集合,它们相互关联,共同完成一个实体任务。
	   每个进程组都有一个进程组长,默认进程组ID与进程组长ID相同。

发信号的几个函数:
alarm 函数:使用自然计时法
	功能:定时发送SIGALRM信号给当前进程
	unsigned int alarm(unsigned int seconds);
		seconds:定时秒数
		返回值:上次定时剩余时间。
			无错误现象。

		alarm(0); 取消定时器
定时器与进程状态无关,就绪、运行、挂起、终止、僵尸...,无论进程处于何种状态,alarm都计时
	time 命令:查看程序执行时间。   自然计时法: 实际时间 = 用户时间 + 内核时间 + 等待时间。  --> 优化瓶颈 IO

setitimer函数:
	功能:同上,更精细一些,虚拟时间计时法,只计算进程占用CPU的时间
	int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
	参数:
		which:	ITIMER_REAL: 采用自然计时。 ——> SIGALRM
			    ITIMER_VIRTUAL: 采用用户空间计时  ---> SIGVTALRM
			    ITIMER_PROF: 采用内核+用户空间计时 ---> SIGPROF
		new_value:定时秒数
		           类型:struct itimerval {
               				struct timeval {
               					time_t      tv_sec;         /* seconds */
               					suseconds_t tv_usec;        /* microseconds */
           				}it_interval;---> 周期定时秒数

               				 struct timeval {
               					time_t      tv_sec;         
               					suseconds_t tv_usec;        

           				}it_value;  ---> 第一次定时秒数  
           			 };
		old_value:传出参数,上次定时剩余时间。
	
		e.g.
			struct itimerval new_t;	
			struct itimerval old_t;	

			new_t.it_interval.tv_sec = 0;
			new_t.it_interval.tv_usec = 0;
			new_t.it_value.tv_sec = 1;
			new_t.it_value.tv_usec = 0;

			int ret = setitimer(&new_t, &old_t);  定时1秒
	返回值:
		成功: 0
		失败: -1 errno

其他几个发信号函数:
	int raise(int sig);
	void abort(void);

在这里插入图片描述

信号集操作函数:
未决信号集不提供用户操作它的接口,阻塞信号集提供。操作阻塞信号集,可以影响未决信号集。
	sigset_t set;  自定义信号集,用这个与阻塞信号集 位操作,从而改变阻塞信号集
	以下函数均操作自定义信号集
	sigemptyset(sigset_t *set);	清空信号集
	sigfillset(sigset_t *set);	全部置1
	sigaddset(sigset_t *set, int signum);	将一个信号添加到集合中
	sigdelset(sigset_t *set, int signum);	将一个信号从集合中移除
	sigismember(const sigset_t *set,int signum); 判断一个信号是否在集合中。 在-->1, 不在-->0

设置 信号屏蔽字(mask)和解除屏蔽:
	int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
		how:SIG_BLOCK  :	设置阻塞
			SIG_UNBLOCK:	取消阻塞
			SIG_SETMASK:	用自定义set替换mask。
		set:	自定义set
		oldset:旧有的 mask。

查看未决信号集:
	int sigpending(sigset_t *set);
		set: 传出的 未决信号集。

【信号捕捉】
注册一个信号捕捉函数,注意,这只是注册,不是调用signal后就捕捉到了信号,信号是内核抓住的
	typedef void (*sighandler_t) (int)
	sighandler_t signal(int signum, sighandler_t handler);
		signum :要捕捉哪个信号
		handler:抓住之后要做什么
该函数由ANSI定义,在不同版本的Unix和不同版本Linux中可能有不同的行为,因此应尽量避免使用它,用下面这个。
	int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 
		signum :要捕捉哪个信号
		act	   :传入参数,新的处理方式
		oldact :传出参数,旧的处理方式
	struct sigaction {
		void (*sa_handler)(int);
		void (*sa_sigaction)(int, siginfo_t *, void *);//一般不用,当用信号做进程间通信 且要携带数据时,用这个回调函数
		sigset_t sa_mask;
		int sa_flags;
		void (*sa_restorer)(void);//废弃
	};

		

信号捕捉特性:

	1. 捕捉函数执行期间,信号屏蔽字 由 mask --> sa_mask , 捕捉函数执行结束。 恢复回mask

	2. 捕捉函数执行期间,本信号自动被屏蔽(sa_flgs = 0).

	3. 捕捉函数执行期间,被屏蔽信号多次发送,解除屏蔽后只处理一次!


借助信号完成 子进程回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值