Linux/Unix编程——进程通信IPC_信号signal

信号signal

信号是给进程的事件通知,可以完成进程间一异步通信,
Unix信号利用进程间通信向进程1发送信号,可使接收进程受信号影响( 终止、挂起、继续)

信号的产生

  1. 命令发出信号 kill
    kill -信号编号 进程id
    注: kill -l 可以查看系统下支持的信号
    1-31 Unix 经典信号,软件开发工程师使用
    34-64 实时信号,驱动开发者使用
    32 33 隐藏保留信号,给NTPL线程库使用
  2. 函数产生信号(显示请求)
    (1)kill(pid_t pid , int signo) 像任意进程发送任意信号
    (2)raise(int signal) 向调回进程发送任意信号
    (3)abort(void) 向调用进程发送SIGABRT信号 退出进程
  3. 终端按键产生信号
    (1)CTL + C 发送 SIGINT(2)
    (2)CTL + \ 终止退出唯一前台进程 SIGQUIT(3)
    (3)CTL + Z 挂起唯一前台进程 SIGSTP(20)
    注: 操作系统中前台进程永远只有一个
    jobs 查看作业编号
    fg 作业编号 唤醒至前台继续执行
    bg 作业编号 唤醒至后台继续执行
  4. 硬件异常产生信号
    (1)段错误:非法操作内存 SIGSEGV(11),将进程杀死
    (2)浮点数例外:cpu/0 SIGFPE(8),将进程杀死
    (3)总线错误: 调度异常 ,SIGBUS(7)
  5. 软条件产生
    (1)定时器,使用alarm 到时间 发送SIGALRM(14)
    (2)管道读端关闭写端向管道写数据内核向写端发送SIGPIPE(13) , 杀死写进程

信号的三种行为

注:使信号失效的三种方式
(1)改变信号行为,将默认行为改为忽略行为,可以失去
(2)改变信号行为,将默认行为改为捕捉行为,可使信号失效
(3)屏蔽信号/阻塞信号,使信号无法递达,不会对进程造成影响(被屏蔽的信号没有丢失,某一刻1接触屏蔽,一样可以递达,影响进程)

高权信号(直接为内核服务,只要发出必然递达)
SIGKILL(9) 只要发出必然杀死进程,无法屏蔽、捕捉、忽略
SIGSTOP(19) 只要发出必然挂起进程,无法屏蔽、捕捉、忽略

默认行为SIG_DEF

有五种默认处理动作

  1. TERM 结束终止进程
  2. CORE 结束进程并且生成转储文件
  3. IGN 进程不受任何信号影响,单纯接收信号
  4. STOP 挂起进程
  5. COUNT 唤醒继续执行
忽略行为SIG_IGN

进程不受信号干涉(进程无影响)
可以让某些信号失去原有的作用

SIGCHLD 信号默认处理动作忽略:父进程使用。子进程结束变为僵尸进程,内核向父进程发送SIGCHLD通知1父进程回收

捕捉行为SIG_ACTION

捕捉特定的信号,为进程服务,信号绑定特定的任务,进程接收到该信号后,自动调用特定任务(信号触发任务)

信号处理过程

  1. 信号发给PCB
  2. PCB 交给未决信号集(未决信号集为1 信号丢弃)
  3. 未决信号集交给屏蔽信号集(屏蔽信号集为1 信号阻塞)
  4. 交给handler->选择信号处理行为->执行信号处理动作

注:未决信号集内核设置,通过但未处理置1 ,处理后置零(标志为一的都是未决态信号)
信号通过未决与屏蔽信号集,进入处理流程,未决对应为0 , 信号切换为递达态
unix 经典信号最大支持一次排队
如果需要查看进程中未处理的信号,应该1打印未决信号集(可以读该信号集,但是用户无法更改)
sigpending(sigset_t * set) 调用该函数,传出进程当前为决信号集

信号捕捉

信号捕捉流程
  1. 定义初始化信号行为结构体
    struct sigaction act;
    act.sa_sigaction = 自定义函数名
    act.sa_flags = 0
    sigenptyset(&act.sa_mask) // 设置屏蔽信号集

  2. 顶哟实现捕捉函数

  3. 将自定义信号行为替换为默认行为
    sigaction(SIGUSR2,&act,&oact); // 信号关联
    注:传出信号行为是为了恢复

特殊捕捉函数 signal
#include <sinal.h>
void ( *signal(int sig, void (*f) (int))) (int);
等价于:
typedef void (*func)(int);
func signal(int sig, func f)
注:
SIG_DFL 恢复信号默认处理机制
SIG_IGN 忽略信号处理
函数地址 调用信号捕获函数执行处理

信号捕捉函数执行过程

进程通常工作于用户层,当信号到达进程,抵达内核层,无法实时处理,只有进程切换到内核空间,才可以检测处理信号并进行处理
可以通过三种方式进行进程状态切换:系统调用、中断、异常
(cpu 权级切换,用户空间cpu 权限低限制大,内核空间权限高可以访问系统所有资源)

可不可冲入函数

不可重入函数:函数内部使用全局资源(全局或静态),如果信号捕捉函数和main主函数一起调用会出现冲突
可重入函数:函数内部没有全局变量,可以放心使用信号捕捉函数

利用信号尽心进程通信

sigqueue(pid_t pid , int signo , sigval_t val)
像任意进程发送任意信号携带任意参数
union sigval
{
int sival_int;
void * sival_ptr;

}

信号屏蔽

  1. 创建屏蔽字集
    sigset_t newset;
  2. 初始化屏蔽字
    sigemptyset(&newset);
  3. 设置屏蔽字
    sigaddset(&newset,SIGINT);
  4. 替换屏蔽字
    sigprocmask(SIG_SETMASK ,&newset ,NULL);

定时器

在UNIX中,定时器的处理是通过信号来完成的
(1)程序使用系统调用向UNIX内核设置定时器信息
(2)定时完成,UNIX内核向进程发送定时器类信号
(3)表示进程捕获定时器类信号,并且执行相关信号处理操作

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
函数alarm在UNIX内核中为调用进程设置一个定时器,进程在调用alarm后seconds秒后,接收到UNIX内核发送到一个SIGALRM信号。
更改信号SIGALRM的默认处理机制,并设置捕获响应函数。
如:signal(SIGALRM, timefunc);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老黑675

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值