linux 进程通讯 信号,Linux(进程间通信-信号)

信号通信是在软件层面上对中断机制的一种模拟。信号是进程间通信机制中唯一的异步通信机制。

信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一进程,而无需知道该进程的状态。如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它为止。

信号事件的产生有硬件来源(如按下键盘或者其他硬件故障)和软件来源,软件来源除了软件调用,还包括一些非法运算等操作。

进程可以通过3种方式来响应一个信号:

1、忽略信号:即对信号不做任何处理,其中,有两个信号不能忽略,SIGKILL & SIGSTOP。

2、捕捉信号:定义信号处理函数,当信号发生时,执行相应的操作。

3、执行默认操作:Linux对每种信号都规定了默认操作,下表包含了部分的定义:

c15aa936897f2fa73bf94aa67d412946.png

信号的相关函数包括信号的发送和设置,具体如下:

发送信号的函数:kill()    raise()    sigqueue()

设置信号的函数:signal()    sigaction()    setitimer()

其他函数:alarm()    pause()

信号发送:kill()    raise()

kill() 函数同kill 系统命令一样,可以发送信号给进程或是进程组(实际上,kill 系统命令就是调用 kill() 函数。需要注意的是,它不仅可以终止进程(发送 SIGTERM信号),也可以向进程发送其他信号。

注意:raise() 函数只能向进程自身发送信号

函数原型:

int kill(pid_t pid,int sig);

int raise(int sig);

说明:pid 为进程号;sig 为信号类型号

raise() 例程:进程在执行while(1)循环输出字符串的时候调用raise(SIGSTOP)使进程停止 \

/* raise.c */

#include

#include

#include

#include

int main()

{

printf("PID: %d\n",getpid());

while(1){

printf("run\n");

raise(SIGSTOP);

}

}

程序输出:

PID: 55859

run

[1]+ Stopped ./a.out

可以看到,进程在输出了第句run之后调用raise(SIGSTOP)使进程停止了,使用命令 "ps -ef | grep a.out" 可以看到进程并没有消失,确认进程只是暂停。使用 "kill -9 55859" 杀死进程。

kill() 例程:子进程间隔10us打印一串字符,父进程100us后 kill 子进程。

/* kill.c */

#include

#include

#include

#include

#include

int main()

{

pid_t pid;

pid = fork();

if(pid == -1){

perror("fork failed:");

exit(-1);

}

if(pid == 0){

while(1){

printf("child\n");

sleep(1);

}

}else{

sleep(3);

kill(pid,SIGINT);

sleep(3);

exit(0);

}

}

alarm() 可以在进程中设置一个定时器,当定时器指定的时间到时,它就向进程发送SIGALARM信号。一个进程只能有一个闹钟,重复设置,前面的闹钟会被覆盖。

示例:

#include

#include

#include

int main()

{

alarm(3);

while(1){

printf("run\n");

sleep(1);

pause();

}

printf("waken up\n");

}

程序输出:

run

Alarm clock

注释掉 pause(); 的程序输出:

run

run

run

Alarm clock

信号的设置:signal()    sigaction()

signal() 用于设置信号的处理函数。主要用于前32种非实时信号的处理,不支持信号传递信息。

注:signal() 是UNIX系统的遗留版本,不同的系统表现不一且在有的系统上会出现信号丢失的问题。且在man中亦提到,’应避免使用signal(),使用sigaction()代替‘。所以这里我们就不讨论signal(),直接使用sigaction()。

函数原型:

int sigaction(int signum,const struct sigaction *act,struct sigacton *oldact);

说明:signum - 信号类型,除SIGKILL & SIGSTOP 外的任何一个信号;act - 指向sigaction结构体的指针,包含对特殊信号的处理;oldact - 保留信号原先的处理方式。

struct sigaction {

void (*sa_handler)(int);

void (*sa_sigaction)(int, siginfo_t *, void *);

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer)(void);

};

说明:

sa_handler 和 sa_sigaction 两者只能定义一个,且sa_sigaction 是 sa_handler的升级版本,由于sa_sigaction又太复杂,在这里我们就不讨论sa_sigaction。

sa_handler 是一个函数指针,指向信号处理函数。它既可以是用户自定义的处理函数,也可以为SIG_DFL(采用默认的处理方式)或SIG_IGN(忽略信号)。信号处理函数只有一个参数,即信号类型。

sa_mask是一个信号集合,用来指定在信号处理函数执行过程中哪些信号被屏蔽。

sa_flags 中包含了许多标志位,都是和信号处理相关的选项。常见可选值包括(SA_NODEFER/SA_NOMASK/SA_NOCLDSTOP/SA_RESTART/SA_ONESHOT/SA_RESETHAND)

sigaction() 示例:

/* signal.c */

#include

#include

#include

#include

void my_func(int sign_no)

{

if(sign_no == SIGINT){

printf("I have got SIGINT\n");

}else

if(sign_no == SIGQUIT){

printf("I have got SIGQUIT\n");

}

}

int main()

{

struct sigaction action;

//初始化结构体

sigaction(SIGINT,0,&action);

action.sa_handler = my_func;

sigaction(SIGINT,&action,0);

sigaction(SIGQUIT,0,&action);

action.sa_handler = my_func;

sigaction(SIGQUIT,&action,0);

printf("Waiting for signal SIGINT & SIGQUIT\n:");

pause();

exit(0);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值