1 信号概述
信号:就是软件中断。信号提供了一种处理异步事件的方法:终端用户键入中断键,则会通过信号机构停止一个程序。所以,信号可以说是进程控制的一部分。
信号的名字都以三个字母开头:SIG
信号是异步事件的经典实例。
2 信号的产生条件
l 当用户按某些终端键时,产生信号。
l 硬件异常产生信号:除数为0、无效的存储访问等等。
l 进程用kill函数可将信号发送给另一个进程或进程组
l 用户可用kill命令将信号发送给其他进程
l 当检测到某种软件条件已经发生,并将其通知有关进程时也产生信号。
3 信号的处理有三种方式:
① 忽略此信号(最常用)
但有2中信号绝对不能忽略:SIGKILL 和 SIGSTOP
原因:这两种信号向超级用户提供了使进程终止或停止的可靠方法。
② 捕捉信号
③ 执行默认动作
4 发出信号的函数
最常用的四个发出信号的系统函数是 kill, raise, alarm 和 setitimer 函数
int kill(pid_t pid,int sig);
int raise(int sig);
unisigned int alarm(unsigned int seconds);
kill 系统调用负责向进程发送信号 sig.
l 如果 pid 是正数,那么向信号 sig 被发送到进程 pid.
l 如果 pid 等于 0,那么信号 sig 被发送到所以和 pid 进程在同一个进程组的进程
l 如果 pid 等于-1,那么信号发给所有的进程表中的进程,除了最大的哪个进程号.
l 如果 pid 由于-1,和 0 一样,只是发送进程组是-pid.
raise 系统调用向自己发送一个 sig 信号.
5 常用的信号屏蔽函数
最常用的信号屏蔽要用到下面的几个函数.
<span style="font-size:18px;">int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signo);
int sigdelset(sigset_t *set,int signo);
int sigismember(sigset_t *set,int signo);
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
</span>
sigemptyset 函数初始化信号集合 set,将 set 设置为空.
sigfillset 也初始化信号集合,只是将信号集合设置为所有信号的集合
sigaddset 将信号 signo 加入到信号集合之中
sigdelset 将信号从信号集合中删除
sigismember 查询信号是否在信号集合之中
sigprocmask 是最为关键的一个函数. 在使用之前要先设置好信号集合 set.这个函数的作用是将指定的信号集合 set 加入到进程的信号阻塞集合之中去,如果提供了 oset 那么当前
的进程信号阻塞集合将会保存在 oset 里面.
参数 how 决定函数的操作方式.
SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中.
SIG_UNBLOCK:从当前的阻塞集合之中删除一个信号集合.
SIG_SETMASK:将当前的信号集合设置为信号阻塞集合.
6 其他信号常用的函数
int pause(void );
int sigsuspend(const sigset_t *sigmask);
pause 函数很简单,就是挂起进程直到一个信号发生了
而sigsuspend 也是挂起进程只是在
调用的时候用sigmask 取代当前的信号阻塞集合.
7 信号量
信号量是一个计数器,用于多进程对共享数据对象的访问。主要是用来保护共享资源,使的资源在一个时刻只有一个进程所拥有.为此我们可以使用一个信号灯.当信号灯的值为某个值的时候,就表明此时资源不可以使用.否则就表示可以使用
为了获得共享资源,进程需要执行下列操作:
1 测试控制该资源的信号量
2 若信号量为正,则可以使用该资源,并使信号量减1,表示了使用了一个资源单位;
3 若信号量为0,则进程进入休眠状态,直至信号量大于0.直至进程被唤醒后,它返回至第一步。
注意:为了正确实现信号量,信号量值得测试及减1操作应当是原子操作。因此,信号量通常是在内核中实现的。
备注:
① POSIX 表示可移植操作系统接口(Portable Operating System Interface ,缩写为 POSIX )
② PV操作了.PV操作是原子操作.也就是操作是不可以中断的,在一定的时间内,只能够有一个进程的代码在 CPU 上面执行.