1.什么是进程间通信?
进程通信就是在不同进程之间传播或交换信息。
进程之间的空间是相互独立的,一般而言是不能相互访问的,唯一的例外是共享内存区。
2.进程间通信的目的
(1)数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间;
(2)共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到
(3)通知事件:一个进程需要向另一个或一组进程发消息,通知他们发生了某个事件
(4)资源共享:多个进程之间共享同样的资源
(5)进程控制:有些进程希望完全控制另一个进程的执行,此时控制进程希望能拦截另一个进程的所有信息和异常,并能够及时知道它的状态。
3.Linux进程间通信的几种方式
管道(Pipe)和有名管道(FIFO)
信号(Signal)
消息队列
共享内存(Shared Memory)
信号量(Semaphore)
套接字(Socket)
管道:管道和命名管道
管道可用于具有亲缘关系进程捡的通信,允许一个进程和另一个与它有公公发祖先的进程之间进行通信;
命名管道:命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能玩,她还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建
管道:管道是单向的、先进先出的,无结构的固定大小的字节流。他把一个进程的标准输出和另一个京城的标准输入连接在一起;
写进程在管道的尾端写入数据,读进程在管道的首段读出数据。数据读出后将从管道中移走,其他读进程都不能再读到这些数据;
管道提供了简单的流控制机制。进程视图读取空管时,在有数据写入管道前,进程将一直被阻塞,同样,管道写满时,进程再试图写管道,在其他进程从管道中移走数据之前,写进程将一直阻塞;
管道只要用于不同进程间通信。
创建一个简单的管道:pipe()
定义函数pipe(int fd[2]),如果系统调用成功,返回0.如果系统调用失败返回-1;
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
int main()
{
int fd[2];
pid_t pid;
char buff[100];
memset(buff,0,100);
if(pipe(fd)<0)
{
printf("pipe error\n");
exit(0);
}
pid = fork();
if(pid == 0)
{
close(fd[1]);
while(1)
{
if(read(fd[0],buff,1)>0)
{
if(buff[0]%3==0&&buff[0]!=0)
printf("%d\n",buff[0]);
if(buff[0]==10)
exit(0);
}
}
close(fd[0]);
}
else
{
close(fd[0]);
for(buff[0]=0;buff[0]<=10;buff[0]++)
{ write(fd[1],buff,1);
sleep(2);
}
close(fd[1]);
wait(NULL);
}
return 0;
}
建立两个无名管道,分别进行读写
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
int main()
{
int pid_fd[2];
int pid_fd1[2];
pid_t pid;
int num;
char buff[100];
memset(buff,0,sizeof(buff));
if(pipe(pid_fd)<0)
{
printf("pipe error\n");
exit(0);
}
if(pipe(pid_fd1)<0)
{
printf("pipe error\n");
exit(0);
}
pid = fork();
if(pid==0)
{
//read pipe
close(pid_fd[1]);
if((num=read(pid_fd[0],buff,100))>0)
{
printf("====[%d] pipe is: %s\n",num,buff);
}
close(pid_fd[0]);
//write pipe
close(pid_fd1[0]);
if(write(pid_fd1[1],"I am son",10)!= -1)
{
printf("Son write success!==\n");
}
close(pid_fd1[1]);
printf("Child Exit\n");
exit(0);
}
else if(pid>0)
{
printf("+++++++++++\n");
close(pid_fd[0]);
if(write(pid_fd[1],"Hello",5)!=-1)
{
printf("parent write success!++\n");
}
close(pid_fd[1]);
//read pipe
close(pid_fd1[1]);
if((num=read(pid_fd1[0],buff,100))>0)
{
printf("++++=[%d] pipe is:%s \n",num,buff);
}
close(pid_fd1[0]);
wait(NULL);
printf("parent Exit !\n");
exit(0);
}
return 0;
}