1. 信号
1.1 产生信号的条件
- 用户在终端按下某些键时,终端驱动程序会发送信号给前台进程,例如Ctrl-C产生
SIGINT
信号,Ctrl-\产生SIGQUIT
信号,Ctrl-Z产生SIGTSTP
信号。 - 硬件异常产生信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为
SIGFPE
信号发送给进程。再比如当前进程访问了非法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV
信号发送给进程。 - 一个进程调用
kill(2)
函数可以发送信号给另一个进程。 - 可以用
kill(1)
命令发送信号给某个进程,kill(1)
命令也是调用kill(2)
函数实现的,如果不明确指定信号则发送SIGTERM
信号,该信号的默认处理动作是终止进程。 - 当内核检测到某种软件条件发生时也可以通过信号通知进程,例如闹钟超时产生
SIGALRM
信号,向读端已关闭的管道写数据时产生SIGPIPE
信号。
1.2 处理信号
如果不想按默认动作处理信号,用户程序可以调用sigaction(2)
函数告诉内核如何处理某种信号(sigaction
函数稍后详细介绍),可选的处理动作有以下三种:
- 忽略此信号。
- 执行该信号的默认处理动作。
- 提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉(Catch)一个信号。
2. 锁
2.1 死锁
当两个线程为了保护两个不同的共享资源而使用了两个互斥锁,那么这两个互斥锁应用不当的时候,可能会造成两个线程都在等待对方释放锁,在没有外力的作用下,这些线程会一直相互等待,就没办法继续运行,这种情况就是发生了死锁。
1. 产生条件
互斥条件:一个资源每次只能被一个线程使用。
持有并等待条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
只要破坏死锁 4 个必要条件之一中的任何一个,死锁问题就能被解决。
2. 解放方案
避免死锁问题就只需要破环其中一个条件就可以,最常见的并且可行的就是使用资源有序分配法,来破环环路等待条件。
线程 A 和 线程 B 获取资源的顺序要一样,当线程 A 是先尝试获取资源 A,然后尝试获取资源 B 的时候,线程 B 同样也是先尝试获取资源 A,然后尝试获取资源 B。所以我们只需将线程 B 改成以相同顺序的获取资源,就可以打破死锁了。