unix编程以及xv6系统浅谈(六)信号

573 阅读2分钟

信号是软件中断。信号名都被定义为正整数常量,不存杂编号为0的信号。

​ 对于信号的处理,有如下的几种方式:

​ (1)忽略此信号:有两种信号绝对不可以忽略,1.SIGKILL和2.SIGSTOP,不能忽略是因为提供了使得进程终止或停止的可靠方法。

​ (2)捕捉信号:要通知内核在某种信号发生的时候,调用一个用户函数。

​ (3)执行系统默认动作

//成功则返回以前的信号处理配置,出错则返回SIG_ERR
//函数的返回值为一个函数指针,该函数中传递一个int类型的参数
void (*signal(int signo,void (*func)(int)))(int)
    signo:
			信号名
	func:
			SIG_IGN		忽略此信号
			SIG_DFL		系统默认动作
			函数指针	所调用的函数,注意signo会作为唯一的int参数传递给这个指针
//注意,内核中定义这些宏的时候是直接定义为函数指针的
#define SIG_ERR		(void (*) ()) -1		//将-1强制转化为函数指针
#define SIG_DFL		(void (*) ()) 0
#define SIG_IGN		(void (*) ()) 1

​ 一个示范的例子

void sig_handler(int sig)
{
    switch(sig):
    {
        case(SIGUSR1):
        	cout<<"SIGUSR1 received"<<endl;
        case(SIGUSR2):
        	cout<<"SIGUSR2 received"<<endl;
    }
}
int main()
{
	if(SIG_ERR==signal(SIGUSR1,sig_handler))
        return -1;
    if(SIG_ERR==signal(SIGUSR2,sig_handler))
        return -1;
}

​ exec函数将原先设置为要捕捉的信号都更改为默认动作,其他信号的状态则保持不变,这是因为人家都执行新的程序了就不要折磨人家了

​ 函数kill将信号发送给进程或者进程组,raise函数允许进程向自身发送信号

//成功则返回0,否则返回-1
int kill(pid_t pid,int signo)
 	pid:
			>0		将信号发送给pid进程
			==0		发送给发送进程同一个进程组中的所有进程
			<0		发送给进程组为pid的绝对值的进程组
			==-1	发送给所有有权限发送的进程
	signo:
			信号
int raise(int signo)
    相当于	kill(getpid(),signo)
//pause函数只有执行了一个信号处理函数并从中返回才会返回
int pause(void)
    挂起直到捕捉到一个信号