UC学习day10 信号的产生 设置进程的信号掩码集 获取进程的未决信号集 信号从产生到处理的整个过程

一 信号的产生
1 硬件产生信号 ctrl+c ctrl+
2 使用命令给进程发送信号
kill -信号编号 pid
3 使用系统调用和库函数实现给进程发送信号
kill(2) raise(3) alarm(2)
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
功能:给进程发送信号
参数:
pid:>0 指定目标进程的pid
sig: 指定具体的信号
返回值:
成功 0
错误 -1 errno被设置

kill -信号编号 pid
tkill 信号编号 pid

编写代码实现 kill命令发送信号的功能
代码参见 tkill.c

使用kill(2)给当前进程发送信号?
kill(getpid(),sig);=====raise(3)

alarm(2)
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:设置一个闹钟,在seconds秒内将SIGALRM信号递达给当前进程
参数:
seconds:指定闹钟的秒数.如果为0.取消原来设置的所有闹钟.未决闹钟
返回值:
如果原来设置到闹钟应该到期的剩余值
如果原来的闹钟

举例说明 使用alarm(2) 设置一个闹钟
代码参见 alarm.c

补充:
pause(2)
#include <unistd.h>
int pause(void);
功能:暂停 等待信号的到达 睡到信号处理以后
参数:
返回值:
只有在信号到达,并处理以后,这个函数才返回,这种情况下,返回-1,errno被设置EINTR.

sleep(3)
使用alarm(2)和pause(2)系统调用完成sleep(3)的功能.
tsleep.
unsigned int tsleep(unsigned int seconds);
代码参见 tsleep.c

二 设置进程的信号掩码集
什么是信号掩码集?
权限掩码集 对信号进行阻塞的.进程可以通过设置自己的信号掩码集来对信号进行阻塞.
信号集类型 sigset_t

typedef struct
{
unsigned long int
__val[32];
} __sigset_t;

32*4=128 byte
1024 bit
跟数据类型相关的操作.
链表 栈 队列 二叉树…
struct node{
int data;
struct node *next;
};
typedef struct node node_t;

struct list{
int count;
node_t *h;
};
typedef struct list list_t;
void insert(void)
list_t *insert_node_to_list(list_t *l,node_t *n)

sigset_t 数据类型
跟类型相关的操作
#include <signal.h>
int sigemptyset(sigset_t *set);
功能:将set信号集初始化为空.也就是说set信号集中不包含任何信号.
参数:
set:指定了要初始化的信号集
返回值:
成功 0
错误 -1 errno被设置

int sigfillset(sigset_t *set);
功能:将信号集set初始化为满,也就是包含所有的信号
参数:
set:指定了要初始化的信号集
返回值:
成功 0
错误 -1 errno被设置

int sigaddset(sigset_t *set, int signum);
功能:将signum信号添加到信号集set中
参数:
set:指定了信号集
signum:指定信号
返回值:
成功 0
错误 -1 errno被设置

int sigdelset(sigset_t *set, int signum);
功能:从信号集set中删除signum信号
参数:
set:指定了信号集
signum:指定了信号
返回值:
成功 0
错误 -1 errno被设置

int sigismember(const sigset_t *set, int signum);
功能:测试信号signum是不是set中的一员
参数:
set:指定了信号集
signum:指定了信号
返回值:
错误 -1 errno被设置
成功 1 代表signum是set中的一员
0 代表signum不是set中的一员

1 定义一个信号集类型变量
2 将这个信号集类型的变量初始化为空
3 将2号信号添加到这个信号集中
4 将3号信号添加到这个信号集中
5 测试3号信号是不是信号集中的成员
6 将3号信号从信号集中删除
7 测试3号信号是不是信号集中的成员
8 测试2号信号是不是信号集中的成员

代码参见 sigset.c
sigprocmask(2)
#include <signal.h>
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
功能:检查或改变阻塞信号集(信号掩码集)
参数:
how:
SIG_BLOCK:将当前进程的信号掩码集和set指定的集合做并集,将其结果设置为当前进程的信号掩码集
SIG_UNBLOCK:将set集合中的成员从当前进程的信号掩码集中移除.
SIG_SETMASK:将set集合设置为进程的信号掩码集
set:这个是用户自定义的信号集类型的一个变量
oldset:如果oldset不为空,将原来的信号掩码集保留到这个空间里
返回值:
成功 0
错误 -1 errno设置错误的原因

设置进程对2号信号阻塞 代码参见 blocked.c

有信号丢失的信号称为不可靠信号 1~31
没有信号丢失的信号称为可靠信号 34~64 实时信号

三 获取进程的未决信号集
sigpending(2)
#include <signal.h>
int sigpending(sigset_t *set);
功能:获取当前进程的未决信号集
参数:
set:指定一个地址空间,将当前进程的未决信号集填充到这个空间里
返回值:
成功 0
错误 -1 errno被设置

举例说明 编写代码获取当前进程的未决信号集
代码参见 pending.c

四 信号从产生到处理的整个过程
以ctrl+c为例讲解
1 在bash上启动一个进程
2 按下ctrl+c键,产生硬件中断.cpu切换到内核态,执行中断处理程序,按键驱动.驱动将这个按键解释为2号信号,将2号信号记录到进程的PCB中.信号已经到达了进程.
3 当进程从内核态切换回用户态的时候,检测进程的PCB中是否有信号的到达.如果没有,切换回用户态,直到进程的结束.
有信号到达,调用信号处理函数.信号处理函数执行完毕,调用sigreturn(2) 返回到内核态.继续执行.
信号递达 信号处理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值