前言:进程间的通信包括
IPC:
1、管道
pipe 无名管道
fifo 有名管道
2、信号 signal <-----------
3、消息队列 System V消息队列 / POSIX消息队列
4、共享内存 System V共享内存 / POSIX共享内存
5、信号量 System V信号量 / POSIX信号量
6、socket套接字
1、信号
信号 是进程间通信的一种方式,这个方式没有传输数据 ,只在内核中传递了一个整数 这个整数值 就是信号值 ,不同的信号值,代表不同的含义,同样的,用户也可以自定义信号,自定义的信号的值和含义,由程序设计者来解释
查看信号值: trap -l
1.1 当一个进程收到一个信号,可能发生5种默认行为 ( man 7 signal )
Term Default action is to terminate the process.
默认行为 是终止进程
Ign Default action is to ignore the signal.
默认行为 是忽略信号
Core Default action is to terminate the process and dump core (see core(5)).
默认行为 输出信息,然后再终止进程
Stop Default action is to stop the process.
默认行为 是停止进程
Cont Default action is to continue the process if it is currently stopped.
默认行为 如果进程当前是停止的,则继续该进程
扩展:
Signal Value Action Comment
──────────────────────────────────────────────────────────────────────
SIGHUP 1 Term Hangup detected on controllinprocessg terminal or death of controlling
控制终端的挂起操作,或者是控制进程的死亡
这个终端上的所有的进程都会收到 SIGHUP
SIGINT 2 Term Interrupt from keyboard
键盘上收到的中断信号 Ctrl c
SIGQUIT 3 Core Quit from keyboard
键盘上收到的退出信号 Ctrl z 或者 Ctrl d
SIGILL 4 Core Illegal Instruction
非法指令 (比如:除数为0)
SIGABRT 6 Core Abort signal from abort(3)
进程正在调用 abort()函数,就会产生 SIGABRT
SIGFPE 8 Core Floating-point exception
浮点数运算运算异常
SIGKILL 9 Term Kill signal
杀死信号 // kill -9 pid
SIGSEGV 11 Core Invalid memory reference
非法内存引用,段错误,就会收到 SIGSEGV
SIGPIPE 13 Term Broken pipe: write to pipe with no readers; see pipe(7)
当你往一个管道文件中写数据时,没有读端,就会收到 SIGPIPE
SIGALRM 14 Term Timer signal from alarm(2)
当进程调用 alarm()函数时,就会产生闹钟信号 SIGALRM
SIGTERM 15 Term Termination signal
终止信号 // kill pid
SIGUSR1 30,10,16 Term User-defined signal 1 用户自定义的信号
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
子进程停止或终止,父进程就会收到 SIGCHLD
SIGCONT 19,18,25 Cont Continue if stopped 如果进程停止了,则继续
SIGSTOP 17,19,23 Stop Stop process 停止
SIGTSTP 18,20,24 Stop Stop typed at terminal 由控制终端发出的停止信号
SIGTTIN 21,21,26 Stop Terminal input for background process
SIGTTOU 22,22,27 Stop Terminal output for background process
注意:
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
SIGKILL 和 SIGSTOP 不能被捕捉、不能被阻塞、不能被忽略。
1.2当一个进程收到一个信号,有3中处理方式:
(1)默认行为
收到一个信号,采用的操作系统的默认行为
(2)忽略信号
(3)捕捉信号
把一个信号 和 用户自定义的处理函数 相关联
那么收到这个信号的时候,就会自动调用 该处理函数
2、信号处理的过程
信号机制的实现原理:是软中断实现的,即打断用户程序的执行
进程上下文:
用户态:在执行用户自己的程序时
内核态:进入到操作系统内核中去执行的
3、Linux操作系统下 与信号相关的接口函数
3.1)发送信号
3.1.1)kill
NAME
kill - send signal to a process
SYNOPSIS
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
功能:发送一个信号sig 给pid指定的进程
参数:
pid:进程pid,指定信号的接受者(可以是多个进程)
pid > 0 pid所代表的那个进程
pid == 0 发送信号给 与 调用进程同组的所有进程
pid == -1 发送给所有进程(慎用)
pid < -1 发送信号给 组id为pid的绝对值的那个进程组 里的所有进程
sig:指定要发送的信号值
返回值:
成功,返回0(至少有一个进程接收到信号)
失败,返回-1,同时errno被设置
给自己发送一个杀死信号
int main()
{
sleep(5);
//给自己发送一个杀死信号
kill( getpid(), 9 ); // SIGKILL
printf("hahahah \n");
while(1);
}
3.1.2)raise() 发送一个信号给自己
NAME
raise - send a signal to the caller
SYNOPSIS
#include <signal.h>
int raise(int sig);
功能:发送一个信号sig给自己 (当前调用进程)
参数:
sig:指定要发送的信号值
返回值:
成功,返回0
失败,返回非0
3.1.3)alarm()
设置定时,在指定的时间后给自己发送一个 SIGALRM 信号
NAME
alarm - set an alarm clock for delivery of a signal
SYNOPSIS
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:定时发送一个闹钟信号SIGALRM给自己
参数:
seconds:指定定时时间(单位:秒)
返回值:
返回,上一次闹钟 剩余的秒数
注意:
闹钟时间一到,当前调用进程 就会收到一个闹钟信号 SIGALRM
同一时刻 一个进程只能有一个闹钟生效
设置一个闹钟的定时时间,会自动把之前的闹钟清除
3.2)捕捉信号
改变信号的处理方式 ,signal() 把 信号 和 用户自定义的处理函数 相关联起来 ---》 捕捉
NAME
signal - ANSI C signal handling
SYNOPSIS
#include <signal.h>
typedef void (*sighandler_t)(int);
功能:把 信号 和 用户自定义的处理函数 相关联起来
参数:
signum:指定要捕捉或者相关联的信号值
handler:函数指针,指定新的信号处理方式
(1)指定用户自定义的信号处理函数
(2)SIG_IGN 忽略信号
(3)SIG_DFL 采用系统默认的信号处理方式
返回值:
成功,返回该信号上一次的处理方式 (第一次返回NULL)
失败,返回SIG_ERR,同时errno被设置
注意:
1)在进程的运行期间 都是可以去捕捉指定的信号的
2)可以让不同的信号 去共享同一个信号处理函数
3)sighandler_t是一个新类型,是一个函数指针类型,指向了一个 带有一个int类型参数且无返回值的函数。也就是用户自定义的信号处理函数的类型:
void xxxx( int signum ) //signum:信号值
{
}
sighandler_t signal(int signum, sighandler_t handler);
写一个程序,设置一个闹钟5s,捕捉闹钟信号,当收到闹钟信号是,打印 "wake up"
在用户按下ctrl c, 进程不死亡,而是打印一句 "收到了 xxx 信号 "
//用户自定义的信号处理函数
void my_handler(int signum)
{
if( signum == SIGALRM )
{
printf("wake up\n");
}
else if( signum == SIGINT )
{
printf("收到了 SIGINT 信号\n");
}
}
int main()
{
//设置一个闹钟5s
alarm( 5 );
//捕捉信号
signal( SIGALRM, my_handler );
signal( SIGINT, my_handler );
//while(1);
pause(); //挂起进程,等待信号到来
}
3)等待一个信号的到来 pause
NAME
pause - wait for signal
SYNOPSIS
#include <unistd.h>
int pause(void);
功能:将进程挂起,直到等待一个信号的到来
参数:无
返回值:
成功,等待了信号
失败,返回-1,同时errno被设置