一:进程通信的原因
1):为了提高计算机系统的效率,增强计算机系统内各种硬件的并行操作能力,操作系统要求程序结构必须适应并发处理的需要,为此引入了进程。
2):由于不同的进程运行在各自不同的内存空间中,一方变量的修改另一方是无法感知到的。因此,进程之间的信息传递不可能通过变量或其它数据结构直接进行,只能通过进程间通信来完成。
二:什么是进程通信:
两个应用程序(进程)之间的交互过程称为进程通信。
三:进程通信的分类
进程通信根据交换信息量的多少和效率的高低,分为低级通信(只能传递状态和整数值)和高级通信(提高信号的通信效率,传递大量数据,减轻程序编制的复杂度),其中,高级进程通信分为三种:共享内存模式,消息传递模式,共享文件模式。
四:进程通信的基本方式:
五:进程通信之信号通信
1):信号通信分为三块内容,分别是信号的发送,信号的接收,信号的处理。信号的发送是由发送进程和内核来完成的,信号的接收和处理是由内核和接收进程来完成的。
2):信号的发送。信号的发送是由内核发送的,内核可以发送很多信号,但不知道发送什么信号和发给用户空间那个进程,因此发送进程要告诉内核这些信息。这就涉及到系统调用函数kill
kill函数:
函数形式: int kill (pid_t pid, int sig)
功能:告诉内核发送sig信号和发给用户空间pid进程,所需的头文件是 #include"signal.h"和#include"sys/types.h".
参数:pid是接收信号的进程,sig是信号的ID值。
返回值:成功返回0,出错则返回-1.
3):信号的接收
接收信号的进程要想收到信号,这个进程就不能结束,可以有如下三种方式来处理:第一种是睡眠函数sleep;第二种是死循环while(1);第三种是使用pause函数。
4):信号的处理
接收信号进程收到信号之后的处理方式有两种,分别是默认处理方式和自己处理方式。默认处理方式通常是终止进程或忽略该信号。接收进程如果是自己处理接收到的信号,则要吧处理信号的方法告诉内核,这涉及到signal函数
函数形式:void( *signal(int signum,void(*handler)(int) )(int)
功能:告诉内核自己处理那个信号和怎样处理这个信号
头文件: #include"signal.h"
参数:signum是信号的ID值,handler为收到信号后的处理方式。
返回值:函数指针 //处理方式是自己定义的一个函数,返回指向处理方式的函数指针。
六:信号通信案列详解
基于Linux的进程通信来模仿听音乐与接电话间的信息交互。
主要知识点:进程通信之信号通信(kill, signal),标准i/o(fwrite, fread, fclose),进程相关命令(ps -axj)。
基本思路:
首先执行listening_music,通过while(1)循环不断模拟听音乐的过程,在这个过程中间,signal函数一直在等待monitoring_phone发过来的信号10/12,当接收到10,将flag标志位置为0,音乐暂停(依旧在while(1)循环当中,只是不再显示listening music.........),此时monitoring_phone依旧执行,且已经监听完成一次,开始模拟接听过程。当接听结束,音乐继续播放,如此,不断循环。
注:两者之间信号的交换是通过kill函数和signal函数,而传递的信号的pid值是随着每一次的编译,而不断改变的,这个问题是怎么解决的?是通过标准i/o来进行文件的保存和读取,且只需要保存一个getpid()返回的pid即可。
具体代码:
server.c
#include"stdio.h" #include"unistd.h" #include"signal.h" #include"sys/types.h" int flag=0; void myfun(int sig) { if(sig==10) { flag=1; } else if(sig==12) { flag=0; } } void listening_music() { int i; for(i=0;i<200;i++) { while(1) { if(flag==0) { break; } } printf("Listening music......i=%d\n",i); usleep(200000); } } void save() { FILE *file=fopen("信号","w+"); if(file==NULL) { perror("fopen"); //即无法打开此文件,并报错 //exit(1); } int i; int h=getpid(); printf("Process id is: %d\n",h); int buffer[]={0}; buffer[0]=h; if( fwrite(buffer,sizeof(int),1,file) == EOF) { printf("文件写入错误!\n"); } fclose(file); } int main() { signal(10,myfun); signal(12,myfun); while(1) { save(); listening_music(); } return 0; }
client.c
#include"stdio.h" #include"unistd.h" #include"signal.h" #include"sys/types.h" void monitoring_phone() { int b=loading(); int i,j; for(i=0;i<150;i++) { printf("monitoring_phone......i=%d\n",i); usleep(200000); } kill(b,10); //10代表的信号即是有电话,停止音乐 for(j=0;j<50;j++) { printf("processing phone......j=%d\n",j); usleep(200000); } kill(b,12); //12代表的信号即是电话结束,音乐继续 } int loading() { FILE *file=fopen("信号","a+"); if(file==NULL) { perror("fopen"); //即无法打开此文件,并报错 fclose(file); //exit(1); } int buf[]={0}; if( fread(buf,sizeof(int),1,file) == EOF) { printf("文件写入错误!\n"); } int a=buf[0]; return a; } int main() { while(1) { monitoring_phone(); } return 0; }