拥有梦想是一种智力,实现梦想是一种能力
概述
若是一个多线程的进程,由于各个线程共享一个地址空间,可以直接通过变量的形式进行通信。而进程,由于各个进程独占一个地址空间,我们需要一种通信机制来完成进程间的数据交互。本章介绍的是信号机制,进程间的通信机制有以下几种:
- 无名管道(pipe)
- 有名管道 (fifo)
- 信号(signal)
- 共享内存(share memory)
- 消息队列(message queue)
- 信号灯集(semaphore set)
- 套接字(socket)
之间有区分与各自的运用场景,其中套接字通常使用在网络服务,其他只能在本地场景下使用。笔者以后会逐一学习,本章介绍信号机制。
信号
信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式 。linux内核通过信号通知用户进程,不同的信号类型代表不同的事件 。
对信号,进程有不同的响应方式
- 缺省方式,默认操作
- 忽略信号,对信号不做任何处理(除了两个不可忽略的信号 SIGKILL和SIGSTOP)
- 捕捉信号,定义用户处理函数
查看所有信号类型
kill -l
常见信号
信号名 | 含义 | 默认操作 |
SIGHUP | 该信号在用户终端关闭时产生,通常是发给和该 终端关联的会话内的所有进程 | 终止 |
SIGINT | 该信号在用户键入INTR字符(Ctrl-C)时产生,内 核发送此信号送到当前终端的所有前台进程 | 终止 |
SIGQUIT | 该信号和SIGINT类似,但由QUIT字符(通常是 Ctrl-\)来产生 | 终止 |
SIGILL | 该信号在一个进程企图执行一条非法指令时产生 | 终止 |
SIGSEV | 该信号在非法访问内存时产生,如野指针、缓 冲区溢出 | 终止 |
SIGPIPE | 当进程往一个没有读端的管道中写入时产生,代 表“管道断裂” | 终止 |
信号名 | 含义 | 默认操作 |
SIGKILL | 该信号用来结束进程,并且不能被捕捉和忽略 | 终止 |
SIGSTOP | 该信号用于暂停进程,并且不能被捕捉和忽略 | 暂停进程 |
SIGTSTP | 该信号用于暂停进程,用户可键入SUSP字符( 通常是Ctrl-Z)发出这个信号 | 暂停进程 |
SIGCONT | 该信号让进程进入运行态 | 继续运行 |
SIGALRM | 该信号用于通知进程定时器时间已到 | 终止 |
SIGUSR1/2 | 该信号保留给用户程序使用 | 终止 |
信号命令 kill\killall
kill并不是要‘杀死’进程,虽然kill大部分的信号是和结束进程相关的,但它确确实实是向进程发送指定的信号。
kill [-signal] pid
- 默认发送SIGTERM
- -sig 可指定信号
- pid 指定发送对象
通常要杀死一个指定的进程
ps aux|grep abc
kill -9 `abc的PID`
killall [-u user | prog]
- prog 指定进程名
- user 指定用户名
killall杀死同名进程
killall -9 bash
这样,bash以及bash相关联的服务进程都会被杀掉。
信号相关函数操作
kill()\raise()信号发送
#include <unistd.h>
#include <signal.h>
int kill(pid_t pid, int sig);
int raise(int sig);
- 成功时返回0,失败时返回EOF
- pid 接收进程的进程号;0代表同组进程; -1代表所有进程
- sig 信号类型
与kill()不同的是,raise()只允许进程向自身发送信号。
alarm()定时发送信号
int alarm(unsigned int seconds);
- 成功时返回上个定时器的剩余时间,失败时返回EOF
- seconds 定时器的时间
- 一个进程中只能设定一个定时器,时间到时产生SIGALRM
ps:alarm经常用于实现超时检测
pause()进程阻塞
int pause(void);
- 进程一直阻塞,直到被信号中断
- 被信号中断后返回-1,errno为EINTR
signal()设置信号的响应方式
#include <unistd.h>
#include <signal.h>
void (*signal(int signo, void (*handler)(int)))(int);
- 成功时返回原先的信号处理函数,失败时返回SIG_ERR
- signo 要设置的信号类型
- handler 指定的信号处理函数: SIG_DFL代表缺省方式; SIG_IGN 代表忽略信号;
示例1
signal()设置信号的响应方式
void handler (int signo) {
if (signo == SIGINT) {
printf(“I have got SIGINT!\n”); }
if (signo == SIGQUIT) {
printf(“I have got SIGQUIT\n”); }
}
int main() {
signal(SIGINT, handler);
signal(SIGQUIT, handler);
while ( 1 ) pause();
return 0;
}
示例2
alarm()定时结束进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
alarm(3);
pause();
printf(“I have been waken up!\n”);
return 0;
}
$ ./a.out
Alarm clock