Linux 信号 模拟实现sleep

1、产生信号

产生信号的3种方式:

1、调用系统函数:kill(); raise(); abort(();

2、软件异常行为;

3、组合键:Ctrl+c Ctrl+d Ctrl+\等;

处理信号的3种方式:

1、忽略。

2、默认(很多情况下是终止)。

3、自定义(信号捕捉)。

信号在内核中的表示:

1、递达:执行信号的处理动作称为信号递达(Delivery)。

2、未决:信号从产生到递达之间的状态,称为信号未决(Pending)。

3、阻塞:进程可以选择阻塞(Block )某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞才执行递达的动作。

注意:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后 可选的一种处理动作。

信号集操作函数

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);

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

void show_pending(sigset_t *set)
{
	int i = 1;
	for(;i<31;i++){
		if(sigismember(set,i))
		{
			printf("1");
		}else{
			printf("0");
		}
	}
	printf("\n");
}
int main()
{
	sigset_t block,oblock,pending;
	sigemptyset(&block);
	sigemptyset(&oblock);
	sigemptyset(&pending);
	sigaddset(&block,2);
	sigprocmask(SIG_SETMASK,&block,&oblock);
	while(1){
		sigpending(&pending);
		sleep(1);
		show_pending(&pending);
	}
	return 0;
}




模拟实现Sleep

1、该程序有bug(无保护机制)

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
int count = 0;
void handler(int sig)
{

}
int mysleep(int second)
{
	struct sigaction act,oact;
	act.sa_handler = handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGALRM,&act,&oact);
	alarm(second);
	pause();
	int time = alarm(0);
	sigaction(SIGALRM,&oact,NULL);
	return time;

}
int main()
{
	while(1)
	{
		printf("hello I am sleping\n");
		mysleep(3);
	}
	return 0;
}


模拟实现Sleep

2、该程序无Bug(有保护机制)

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
int count = 0;
void handler(int sig)
{}
int mysleep(int second)
{
	struct sigaction act,oact;
	sigset_t nmask,onmask,unmask;
	//信号捕捉动作设置
	act.sa_handler = handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGALRM,&act,&oact);
	//信号屏蔽设置
	sigemptyset(&nmask);
	sigaddset(&nmask,SIGALRM);
	sigprocmask(SIG_BLOCK,&nmask,&onmask);
	alarm(second);//设置闹钟
	//解除信号屏蔽
	unmask = onmask;
	sigdelset(&unmask,SIGALRM);
	sigsuspend(&unmask);
	int time = alarm(0);
	sigaction(SIGALRM,&oact,NULL);
	return time;

}
int main()
{
	while(1)
	{
		printf("hello I am sleping\n");
		mysleep(3);
	}
	return 0;
}




注:

1. 调用sigprocmask(SIG_BLOCK, &nmask, &omask);时屏蔽SIGALRM。

2. 调用sigsuspend(&unpmask);时解除对SIGALRM的屏蔽,然后挂起等待待。

3. SIGALRM递达后suspend返回,自动恢复原来的屏蔽字,也就是再次屏蔽SIGALRM。

4. 调用sigprocmask(SIG_SETMASK, &oldmask, NULL);时再次解除对SIGALRM的屏蔽。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值