嵌入式linux的学习笔记-进程间通信的信号与信号集(四)
采用raise发送信号
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid; //建立进程ID
int ret;
if((pid=fork())<0)
{
//创建子进程出错,出错处理
}
if(pid==0)
{
//子进程中
raise(SIGSTOP); //子进程发送一个信号
//终止信号
exit(0); //子进程退出
}else
{
printf("pid=%d\n",pid);
if(waitpid(pid,SIGKILL)==0) //等待子进程的关闭,如果成功,则返回0
{
printf("kill %d\n",pid);
exit(0);
}
}
}
pause()
功能:让进程暂停直到信号出现
相关函数: kill,signal,sleep
表头文件: #include<unistd.h>
定义函数: int pause(void);
函数说明: pause()会令目前的进程暂停(进入睡眠状态),直到被信号(signal)所中断。
例子:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main( void )
{
alarm( 5 ); //定义一个闹钟,5秒后发送一个闹钟超时信号
pause(); //系统挂起,等待一个信号将它唤醒
return 0;
}
//改程序在执行5秒钟后退出
signal 定义一个信号的处理方式或者指定处理函数,这个函数已经在linux里被sigaction所取代,所以尽量不要使用它了
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void my_func(int sign_no) //用户自定义信号处理程序
{
if(sign_no==SIGINT) //判断信号类型
{
printf("SIGINT\n");
}
if(sign_no==SIGQUIT) //判断信号类型
{
printf("SIGQUIT\n");
}
}
int main()
{
signal(SIGINT,my_func); //注册函数,指定遇到SIGINT时采用用户自定义的my_func函数处理
signal(SIGQUIT,myfunc); //注册函数,指定遇到SIGQUIT时采用用户自定义的my_func函数处理
pause(); //系统挂起,等待信号将它唤醒,当遇到 SIGINT或者SIGQUIT任何一个信号时,进程都会打印对应信息,并且退出
//如果遇到其他信号时,进程将直接退出
exit(0);
}
信号集的处理
int sigemptyset(sigset_t *set); //创建set并且情况信号集
int sigfillset(sigset_t *set); //创建set并使set包含所有linux的信号
int addset(sigset_t *set,int signo); //给set信号集增加一个signo信号
int sigdelset(sigset_t*set,int signo); //将set信号集中的signo定义的信号剔除
以上四个函数成功调用返回0,失败返回1
int sigismember(const sigset_t *set,int signo); //判断set信号集中是否已经包含signo所指向的信号,真返回1,假返回0
int sigprocmask(int how,const sigset_t *set,sigset_t *oset); //设置信号集的屏蔽位,如果oset不为NULL,则oset返回当前修改之前的屏蔽字
how的参数定义
SIG_BLOCK : 屏蔽set所包含的所有信号
SIG_UNBLOCK : 解除set所包含的所有信号
SIG_SETMASK : 直接设置屏蔽信号所指向的值给set信号集
int sigaction(int signo,const struct sigction *act,struct sigaction *oact);
sigaction函数的功能是检测或者修改signo信号关联的处理动作
signo是要检测或者修改具体动作的信号编号数,若act非NULL,则修改它的动作,如果oact非NULL,则返回该信号的原先动作
struct sigaction{
void (*sa_handler)(int signo); //用户自定义处理函数,或者SIG_DFL或者 SIG_IGN
sigset_t sa_mask; //信号集,用来指导在信号处理指向过程中哪些信号要被阻塞
int sa_flags; //信号选项,包括是否则色,是否忽略SIGSTOP,SIGSTP,SIGTTIN,SIGTTOU信号,是否自定义信号只执行一次等等
void (*as_restore);
}
int sigpending(sigset_t *set); //用于检测set信号集中是否为未决的信号,比如在信号集阻塞时的信号
例子
void my_func(int signo) //用户自定义信号处理函数
{
print("test SIGQUIT\n");
}
int main()
{
sigset_t set,pendset; //创建信号集与未决信号集
struct sigaction at1,at2;
sigemptyset(&set);
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGINT);
sigprocmask(SIG_BLOCK,&set,NULL); //阻塞上述两个添加入信号集的两个信号
sleep(10); //进程休眠10秒,再次期间set信号集的两个信号都无法响应
sigprocmask(SIG_UNBLOCK,&set,NULL); //解除set的阻塞
while(1)
{
if(sigismember(&set,SIGINT)) //检测SIGINT信号是否在我们的set信号集当中
{
sigmptyset(&at1.sa_mask); //滞空信号集
at1.as_handler=myfunc; //指定处理函数
sigaction(SIGINT,&at1,NULL); //注册当遇到SIGINT信号的处理方式
}else if(sigismember(&set,SIGQUIT))
{
sigemptyset(&at2.sa_mask);
at2.sa_handler=SIGDFL; //采用默认方式
sigaction(SIGTERM,&at2,NULL); //注册遇到SIGTERM信号的处理方式
}
}
}
以上的这个例子中,当解除set阻塞后,采用sigaction的方式修改了SIGINT(中断进程,键盘的ctrl+c与)与SIGTERM(软件中断信号,键盘的ctrl+\)的处理方式