Linux系统提供了多种进程之间的通信方式
例如:无名管道,有名管道,信号等
1、如果是同一进程下的多个线程,共享资源,所以线程之间的通信只需要注意互斥和同步即可。
2、如果是多个进程。由于进程之间不共享资源,所以进程间的通信需要用到,系统提供的内核空间。
1、无名管道
1、本质也是一个内核空间的文件,存储在内存中,读写数据都是一次性的。
2、无名管道写入数据后,一旦读出数据,数据就消失了。
3、无名管道,一旦打开,就出现读端和写端,如果进行读取数据,就要先关闭写端,如果想要写数据,就要先关闭读端。
4、无名管道工作原理是半双工,也就是同一时刻只能是A写B读,或者A读B写。
5、无名管道只能进行亲缘进程间的通信。
6、管道文件相关的函数属于文件IO部分,只能使用文件IO读写。
7、管道的读写端属于文件描述符,也遵循最小未分配原则。
单工:只能是A向B发信息,B不能向A发信息。
半双工:同一时刻只能A向B发信息,或者B向A发信息。
全双工:同一时刻AB都是收发信息。
无名管道API:
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建一个无名管道.pipefd[0]读端 pipefd[1]:写端
参数:文件描述符数组
返回值:成功返回0,失败返回-1,并置位错误码。
eg: int pipefd[2];
if(pipe(pipefd)==-1)
{
perror("pipe");
return -1;
}
1、当读端存在时,有多少就写多少,写够2^16K为止
2、当写端存在时,有多少就读多少,读完为止会在read处阻塞。
3、当读端不存在,写入管道,会导致管道破裂。
4、当写端不存在时,有多少就读多少,读完为止不会在read处阻塞。
2、有名管道
1、有名字的管道,相对于无名管道,可以进程非亲缘进程间的通信。
2、有名管道写入一次读取一次。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
功能:创建一个有名管道用于非亲缘进程间的通信
参数1:有名管道名
参数2:创建时的权限。
返回值:成功返回0,失败返回-1,并置位错误码
3、信号
1、进程间除了管道之外还可以使用信号通信。
2、中断是硬件的操作,信号是模拟硬件的中断。
3、信号可以由内核发送给进程,可以由用户发送给进程,还可以由进程发送给进程。
4、信号的发送接收属于异步通信,也就是各个进程之间互不影响。
5、信号的处理方式三种:默认,忽略,捕获(由用户自定义处理方式)。
6、9) SIGKILL,SIGSTOP既不能忽略也不能捕获,只能执行。
信号种类:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
1) SIGHUP:终端要关闭了,终端会向该终端下运行的所有进程发送一个信号,我要关闭了你们都退了吧。
2) SIGINT:按下ctrl +c键,终止进程。
3) SIGQUIT:按下ctrl +\键,终止进程,会生成一个core dump文件,记录终止进程的状态。 9) SIGKILL:杀死进程,包括后台运行的进程。
10) SIGUSR1,12) SIGUSR2:用户自定义的信号。
11) SIGSEGV:由内核向用户空间发送的段错误信号。
14) SIGALRM:由系统向调用进程发送的定时器信号。
17) SIGCHLD:子进程退出时发送给父进程的信号,告诉父进程他要死了。
18) SIGCONT:将暂停的进程继续运行信号。
19) SIGSTOP:内核发送给进程的暂停信号。
20) SIGTSTP:用户按下了ctrl+z键,暂停进程。
信号发送函数signal
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:信号处理函数,忽略,默认和捕获操作。
参数1:信号号
参数2: SIG_IGN:忽略信号,不执行任何的操作。
SIG_DFL:默认信号,执行信号原始的操作。
自定义函数:捕获,某个信号,捕获的信号处理方式由程序员决定。
返回值:成功返回前一个信号号,失败返回SIG_ERR, 并置位错误码。
SIGALRM信号使用,模拟下棋alarm函数
#include <unistd.h> unsigned
int alarm(unsigned int seconds);
功能:设置定时时间,时间到了内核会向调用进程发送SIGALRM信号 如果第二次设置了定时时间,那么alarm函数返回的是上一次剩余的秒数。
参数:设置的秒数。
返回值:成功返回上一次预定的剩余秒数,如果没有上一次预定的秒数返回0
信号发送函数:kill raise
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
功能:发送信号给调用进程的函数,可以给自己发送信号也可以给其他进程发送信号
参数1:进程号 >0:向指定的进程号发送信号
=0:向调用进程所在的进程组中每一个进程发送信号。
=-1:向任意的进程发送信号
<-1:向进程组ID为pid绝对值的所有进程发送信号。
参数2:发送的信号号
返回值:成功返回0,失败返回-1,并置位错误码。
#include <signal.h>
int raise(int sig);
功能:调用进程向自己发送一个信号
参数:信号号
返回值:成功返回0,失败返回非0.
思维导图