信号的共性:
信号的本质
未决
递达
信号处理方式
阻塞信号集(信号屏蔽字):
本质:位图,用来记录信号的屏蔽状态
未决信号集
kill函数、命令产生信号
#include
int kill(pid_t pid,int sig); //发送信号给一个指定的进程。
pid: >0 发送信号给指定进程
=0 发送信号给调用kill函数的那个进程,处于同一进程组的进程
<1: 取绝对值,当作进组id,发送信号给该进程组的所有组员。kill -SIGKILL -9527
-1:发送信号给有权限发送的所有进程
sig:信号编号
返回值:
成功:0
失败:-1,errno
案例
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sys_err(const char*str)
{
perror(str);
exit(1);
}
int main(int argc,char*argv[])
{
pid_t pid = fork();
if(pid == 0)
{
sleep(2);
kill(getppid(),SIGKILL);
}
else if(pid > 0)
{
while(1)
{
printf("I'm a parent,pid = %d\n",getpid());
usleep(10000);
}
}
return 0;
}
alarm函数产生信号
unsigned int alarm(unsigned int seconds); // 设置定时,发送SIGALARM信号
seconds:定时的秒数.
返回值:
上次定时剩余实现
不会出错
alarm(0):取消闹钟
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sys_err(const char*str)
{
perror(str);
exit(1);
}
int main(int argc,char*argv[])
{
// 设置1s的定时器
alarm(1);
int i = 0;
for(i = 0;;i++)
{
printf("i = %d\n",i);
}
return 0;
}
#include
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
功能:
设置定时器(闹钟)。 可代替alarm函数。精度微秒us,可以实现周期定时。
参数:
which:指定定时方式
a) 自然定时:ITIMER_REAL → 14)SIGALRM计算自然时间
b) 虚拟空间计时(用户空间):ITIMER_VIRTUAL → 26)SIGVTALRM 只计算进程占用cpu的时间
c) 运行时计时(用户 + 内核):ITIMER_PROF → 27)SIGPROF计算占用cpu及执行系统调用的时间
new_value:struct itimerval, 负责设定timeout时间
struct itimerval {
struct timerval it_interval; // 闹钟触发周期
struct timerval it_value; // 闹钟触发时间
};
struct timeval {
long tv_sec; // 秒
long tv_usec; // 微秒
}
itimerval.it_value: 设定第一次执行function所延迟的秒数
itimerval.it_interval: 设定以后每几秒执行function
old_value: 存放旧的timeout值,一般指定为NULL
返回值:
成功:0
失败:-1
void myfunc(int sig)
{
printf("hello\n");
}
int main()
{
struct itimerval new_value;
//定时周期
new_value.it_interval.tv_sec = 1;
new_value.it_interval.tv_usec = 0;
//第一次触发的时间
new_value.it_value.tv_sec = 2;
new_value.it_value.tv_usec = 0;
signal(SIGALRM, myfunc); //信号处理
setitimer(ITIMER_REAL, &new_value, NULL); //定时器设置
while (1);
return 0;
}
#include
sigset_t set ; 自定义信号集 //typedef unsigned long sigset_t
int sigemptyset(sigset_t *set); //将set集合置空
int sigfillset(sigset_t *set); //将所有信号加入set集合
int sigaddset(sigset_t *set, int signo); //将signo信号加入到set集合
int sigdelset(sigset_t *set, int signo); //从set集合中移除signo信号0 -1
int sigismember(const sigset_t *set, int signo); //判断信号是否存在1 0
#include
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能:
检查或修改信号阻塞集,根据 how 指定的方法对进程的阻塞集合进行修改,新的信号阻塞集由 set 指定,而原先的信号阻塞集合由 oldset 保存。
参数:
how : 信号阻塞集合的修改方法,有 3 种情况:
SIG_BLOCK:向信号阻塞集合中添加 set 信号集,新的信号掩码是set和旧信号掩码的并集。相当于 mask = mask|set。
SIG_UNBLOCK:从信号阻塞集合中删除 set 信号集,从当前信号掩码中去除 set 中的信号。相当于 mask = mask & ~ set。
SIG_SETMASK:将信号阻塞集合设为 set 信号集,相当于原来信号阻塞集的内容清空,然后按照 set 中的信号重新设置信号阻塞集。相当于mask = set。
set : 要操作的信号集地址。
若 set 为 NULL,则不改变信号阻塞集合,函数只把当前信号阻塞集合保存到 oldset 中。
oldset : 保存原先信号阻塞集地址
返回值:
成功:0,
失败:-1,失败时错误代码只可能是 EINVAL,表示参数 how 不合法。
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sys_err(const char*str)
{
perror(str);
exit(1);
}
// 创建函数,打印未决的每一个二进制位
void print_pedset(sigset_t*set)
{
int i = 0;
for (i=1;i<32;i++)
{
if(sigismember(set,i))
{
putchar('1');
}
else
{
putchar('0');
}
}
printf("\n");
}
int main(int argc,char*argv[])
{
//自定义信号集
sigset_t set, oldset,pedset;
// 清空自定义信号集合
sigemptyset(&set);
//将2号信号添加到自定义信号集
sigaddset(&set, SIGINT);
// 借助自定义信号,设置pcb中的信号屏蔽字中的2号信号为屏蔽、
int ret = sigprocmask(SIG_BLOCK,&set, &oldset);
if(ret == -1)
sys_err("sigprocmask error");
while(1)
{
// 获取当前的未决信号集
ret = sigpending(&pedset);
if(ret == -1)
sys_err("sigpending error");
// 打印未决信号集
print_pedset(&pedset);
sleep(1);
}
return 0;
}
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
参1:待捕捉的信号编号
参2; 一旦捕捉到该信号,执行的回调函数
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sys_err(const char*str)
{
perror(str);
exit(1);
}
void sig_catch(int signum)
{
if(signum == SIGINT)
printf("catch you!! %d\n",signum);
else if(signum == SIGQUIT)
{
printf("哈哈,%d,你被我抓住了\n",signum);
}
return ;
}
int main(int argc,char*argv[])
{
// 注册信号捕捉函数
signal(SIGINT,sig_catch);
signal(SIGQUIT,sig_catch);
while(1); //模拟当前进程还有很多代码药执行
return 0;
}
#include
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
功能:
检查或修改指定信号的设置(或同时执行这两种操作)。
参数:
signum:要操作的信号。
act: 要设置的对信号的新处理方式(传入参数)。
oldact:原来对信号的处理方式(传出参数)。
如果 act 指针非空,则要改变指定信号的处理方式(设置),如果 oldact 指针非空,则系统将此前指定信号的处理方式存入 oldact。
返回值:
成功:0
失败:-1
struct sigaction {
void(*sa_handler)(int); //旧的信号处理函数指针
void(*sa_sigaction)(int, siginfo_t *, void *); //新的信号处理函数指针
sigset_t sa_mask; //信号阻塞集
int sa_flags; //信号处理的方式
void(*sa_restorer)(void); //已弃用
};
a) SIG_IGN:忽略该信号
b) SIG_DFL:执行系统默认动作
c) 处理函数名:自定义信号处理函数
Ø SA_RESTART:使被信号打断的系统调用自动重新发起(已经废弃)
Ø SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
Ø SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
Ø SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
Ø SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
Ø SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sys_err(const char* str)
{
perror(str);
exit(1);
}
void sig_catch(int signum)
{
if(signum == SIGINT)
printf("catch you!! %d\n", signum);
else if(signum == SIGQUIT)
{
printf("哈哈, %d, 你被我抓住了\n", signum);
}
return;
}
int main(int argc, char* argv[])
{
struct sigaction act, oldact;
act.sa_handler = sig_catch;
sigemptyset(&(act.sa_mask));
sigaddset(&act.sa_mask,SIGQUIT);
act.sa_flags = 0; // 本信号自动屏蔽
// 注册信号捕捉函数
int ret = sigaction(SIGINT, &act, &oldact);
if(ret == -1)
{
sys_err("sigaction error");
}
while(1) {
// Add some code here if needed
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sys_err(const char* str)
{
perror(str);
exit(1);
}
void catch_child(int signum)
{
pid_t wpid;
int status;
// if((wpid = wait(NULL))!=-1)//会产生僵尸进程
// {
// printf("catch child pid = %d\n",wpid);
// }
while((wpid = waitpid(-1,&status,0))!=-1)
{
if(WIFEXITED(status))
{
printf("catch child wpid = %d\n",wpid);
}
}
}
int main(int argc,char*argv[])
{
int i;
pid_t pid ;
for(i = 0;i<5;i++)
{
pid=fork();
if(pid==0)
{
break;
}
}
if( 5== i)
{
struct sigaction act;
act.sa_handler = catch_child;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD,&act,NULL);
printf("I'm a parent,pid = %d\n",getpid());
while(1);
}
else
{
printf("I'm a child,pid = %d\n",getpid());
}
return 0;
}