目录
信号机制
信号特质
信号共性
信号产生以及处理方式
信号产生
递达:递送并到达进程
未决:产生和递达之间的状态,主要由于阻塞(屏蔽)导致该状态
信号处理方式
- 执行默认动作
- 忽略(丢弃)
- 捕捉(调用户处理函数)
阻塞信号集和未决信号集
阻塞信号集(信号屏蔽字)
未决信号集
信号查看
kill -l
可以查看当前信号系统可以使用的信号有哪些
不存在编号为0的信号,其中1-31号信号称之为常规信号(也叫常规信号或标准信号),34-64称之为实时信号,驱动编程与硬件相关。名字上区别不大。而前32个名字各不相同
信号四要素
信号编号,信号名称,信号对应事件,信号默认处理操作
可以使用下面命令查看
man 7 signal
常用信号
kill函数/信号产生
kill命令产生信号:kill -SIGKILL pid
kill函数:给指定的进程发送指定信号(一定不杀死)
int kill(pid_t pid, int sig);
成功:0
失败:-1
非法,普通用户杀死init进程等权级问题,设置error
eg:
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<errno.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid=fork();
if(pid<0)
{
perror("fork");
exit(1);
}
else if(pid==0)//子进程
{
printf("child pid = %d ,ppid = %d\n",getpid(),getppid());
sleep(2);
kill(getppid(),SIGKILL);
}
else//父进程
{
printf("parent pid = %d\n",getpid());
while(1);
}
return 0;
}
结果:
alarm函数
设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送 14 SIGALRM信号。进程收到该信号,默认动作终止
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
返回值:
上次定时剩余时间
无错误现象
定时,与进程状态无关(自然定时法)!就绪,运行,终止,挂起(阻塞,暂停),僵尸…无论进程处于何种状态,alarm都会计时。
eg: 编写程序测试你使用的计算机1秒能数对多少个数。
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<errno.h>
#include<unistd.h>
int main()
{
int i=0;
alarm(1);
while(1)
printf("%d\n",i++);
return 0;
}
time命令可以查看程序执行的时间
实际执行时间=系统时间+用户时间+等待时间
setitimer函数
setitimer函数为设置定时器(闹钟),可替代alarm函数,比alarm函数精确度更高,精度为微秒,可以实现周期定时。
返回值
成功返回 0
失败返回 -1 error
参数
struct itimerval 结构体
struct itimerval {
struct timeval it_interval; /* Interval for periodic timer */
struct timeval it_value; /* Time until next expiration */
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
eg : 编写程序测试你使用的计算机1秒能数对多少个数
#include<stdio.h>
#include<sys/time.h>
int main()
{
int i=0;
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; //微妙
if(setitimer(ITIMER_REAL,&new_t,&old_t)==-1)
{
perror("setitimer error");
return -1;
}
while(1)
printf("%d\n",++i);
return 0;
}
信号集操作函数
自定义信号集操作函数
#include <signal.h>
int sigemptyset(sigset_t *set); //清空信号集,全置为零
int sigfillset(sigset_t *set); //填满信号集 ,全置为一
int sigaddset(sigset_t *set, int signum); //将一个信号添加到信号集中
int sigdelset(sigset_t *set, int signum);//将一个信号从信号集中移除
int sigismember(const sigset_t *set, int signum);
//判断一个信号是否在信号集合中(在返回1,不在返回0)
设置信号屏蔽字和解除屏蔽
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
参数:
how
set
oldset
查看未决信号集
int sigpending(sigset_t *set);
set :传出的未决信号集
eg: 练习阻塞SIGNIT信号并查看
#include<stdio.h>
#include<signal.h>
void print(sigset_t set)
{
int i=0;
for(i=0;i<32;i++)
{
if(sigismember(&set,i))
putchar('1');
else
putchar('0');
}
printf("\n");
}
int main()
{
sigset_t set;
sigset_t oldset;
sigset_t pedset;
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_BLOCK,&set,&oldset);
sigpending(&pedset);
print(pedset);
while(1);
return 0;
}
信号捕捉
signal函数
注册一个信号捕捉函数
#include <signal.h>
typedef void (*sighandler_t)(int); //函数指针
sighandler_t signal(int signum, sighandler_t handler);
eg:
#include<signal.h>
#include<stdio.h>
void sig_catch(int signo)
{
printf("catch you ! %d\n",signo);
}
int main()
{
signal(SIGINT,sig_catch);
while(1);
return 0;
}
sigaction函数
修改信号处理动作(通常在Linux用其注册一个信号的捕捉函数)
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
参数:
act : 传入参数,新的处理方式
old: 传出参数,旧的处理方式
struct sigaction
{
void (*sa_handler)(int); //捕捉到信号后要干的事情
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //只作用于信号捕捉期间
int sa_flags;
void (*sa_restorer)(void);
};
eg:捕捉信号SIGINT
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
void sig_catch(int signo)
{
printf("catch you ! %d\n",signo);
}
int main()
{
struct sigaction act,oldact;
act.sa_handler = sig_catch;//set callback function name
sigemptyset(&act.sa_mask);//清零set mask when sig_catch working
act.sa_flags=0; //usually use
int ret=sigaction(SIGINT,&act,&oldact);
if(ret==-1)
{
perror("error");
exit(1);
}
while(1);
return 0;
}
信号捕捉特性
测试:
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void sig_catch(int signo)
{
printf("catch you ! %d\n",signo);
sleep(3);
}
int main()
{
struct sigaction act,oldact;
act.sa_handler = sig_catch;//set callback function name
sigemptyset(&act.sa_mask);//清零set mask when sig_catch working
act.sa_flags=0; //usually use
int ret=sigaction(SIGINT,&act,&oldact);
if(ret==-1)
{
perror("error");
exit(1);
}
while(1);
return 0;
}