1.什么是进程间的通信(解决什么问题)
父子进程(数据的收发)
两个毫无关联的进程之间的通信(数据的收发)
2.有哪些通信方式
管道:无名管道和有名管道
信号:
共享内存:
消息队列:
信号量:
套接字编程:
3.管道
3.1 无名管道
(1)相关的接口函数
创建无名管道
int pipe(int fildes[2]);
返回值:成功 0 失败 -1
参数:fildes --》存放的是文件描述符
fildes[0] --》读端的文件描述符
fildes[1] --》写端的文件描述符
(2)无名管道的特点
见图示
3.2 有名管道
(1)相关的接口函数
第一步:创建有名管道
int mkfifo(const char *pathname, mode_t mode);
返回值: 成功 0 失败 -1
参数:pathname --》你要创建的有名管道的路径名
mode --》权限 0777
第二步:open打开你刚才创建的有名管道
第三步:使用read/write往有名管道中读写数据
第四步:关闭有名管道
close
(2)有名管道的特点
特点1: 有名管道只能在纯粹的linux环境中创建,不能在共享路径下创建(管道文件是属于linux系统特有的一种文件类型,windows不支持该文件类型)
特点2:进程1写入hello到有名管道中,然后退出了
进程2运行,读取有名管道中的内容,发现读取不了
特点3:管道不能使用lseek()去设置读写偏移
3.3 有名管道和无名管道的区别
区别1:有名管道创建成功以后会在系统中产生管道文件
无名管道创建成功以后没有管道文件,只有文件描述符
区别2:有名管道没有固定的读写端,可以随意读写
无名管道有固定的读写端,不能用错
区别3:有名管道既能用于血缘关系的进程间通信,也能用于没有任何血缘关系的进程间通信
无名管道只能用于血缘关系的进程间通信
无名管道弄错啦读写端
#include "myhead.h"
//父子进程采用无名管道单向通信
//儿子给父亲发送信息
int main()
{
char buf[100];
int fd[2];
//创建一个无名管道
int ret=pipe(fd);
if(ret==-1)
{
printf("创建无名管道失败!\n");
return -1;
}
//生个仔
pid_t id=fork();
if(id>0) //父
{
while(1)
{
//从无名管道的读端去读取内容
read(fd[1],buf,100); //用错了文件描述符,导致read不会阻塞了
printf("儿子发送过来的信息是:%s\n",buf);
}
}
else if(id==0) //子
{
while(1)
{
bzero(buf,100);
printf("请输入要发送给老爸的信息!\n");
scanf("%s",buf);
//使用写端把buf写入到无名管道中
write(fd[0],buf,strlen(buf)); //弄错了写端的文件描述符
}
}
}
父子进程采用无名管道单向通讯
#include "myhead.h"
//父子进程采用无名管道单向通信
//儿子给父亲发送信息
int main()
{
char buf[100];
int fd[2];
//创建一个无名管道
int ret=pipe(fd);
if(ret==-1)
{
printf("创建无名管道失败!\n");
return -1;
}
//生个仔
pid_t id=fork();
if(id>0) //父
{
while(1)
{
//从无名管道的读端去读取内容
read(fd[0],buf,100);
printf("儿子发送过来的信息是:%s\n",buf);
}
}
else if(id==0) //子
{
while(1)
{
bzero(buf,100);
printf("请输入要发送给老爸的信息!\n");
scanf("%s",buf);
//使用写端把buf写入到无名管道中
write(fd[1],buf,strlen(buf));
}
}
close(fd[0]);
close(fd[1]);
return 0;
}
一个无名管道实现父子进程单向通讯
#include "myhead.h"
//父子进程采用无名管道双向通信
int main()
{
char buf[100];
char otherbuf[100];
int fd1[2];
//创建一个无名管道
int ret=pipe(fd1);
if(ret==-1)
{
printf("创建无名管道失败!\n");
return -1;
}
//生个仔
pid_t id=fork();
if(id>0) //父
{
while(1)
{
bzero(buf,100);
bzero(otherbuf,100);
//从无名管道的读端去读取内容
read(fd1[0],buf,100);
printf("儿子发送过来的信息是:%s\n",buf);
//回复信息给儿子
printf("请输入要回复给儿子的信息!\n");
scanf("%s",otherbuf);
write(fd1[1],otherbuf,strlen(otherbuf));
sleep(1); //目的为了防止父进程写入管道的信息,立马被父进程自己读取出来了
}
}
else if(id==0) //子
{
while(1)
{
bzero(buf,100);
bzero(otherbuf,100);
printf("请输入要发送给老爸的信息!\n");
scanf("%s",buf);
//使用写端把buf写入到无名管道中
write(fd1[1],buf,strlen(buf));
sleep(1); //目的为了防止子进程写入管道的信息,立马被子进程自己读取出来了
//从管道里面读取信息
read(fd1[0],otherbuf,100);
printf("父亲发送给我的信息是:%s\n",otherbuf);
}
}
}
两个无名管道实现父子进程的双向通讯
#include "myhead.h"
//父子进程采用无名管道双向通信
int main()
{
char buf[100];
char otherbuf[100];
int fd1[2];
int fd2[2];
//创建两个无名管道
int ret=pipe(fd1);
if(ret==-1)
{
printf("创建无名管道失败!\n");
return -1;
}
ret=pipe(fd2);
if(ret==-1)
{
printf("创建无名管道失败!\n");
return -1;
}
//生个仔
pid_t id=fork();
if(id>0) //父
{
while(1)
{
bzero(buf,100);
bzero(otherbuf,100);
//从第一个无名管道的读端去读取内容
read(fd1[0],buf,100);
printf("儿子发送过来的信息是:%s\n",buf);
//回复信息给儿子
printf("请输入要回复给儿子的信息!\n");
scanf("%s",otherbuf);
//把信息写入到第二个无名管道中
write(fd2[1],otherbuf,strlen(otherbuf));
}
}
else if(id==0) //子
{
while(1)
{
bzero(buf,100);
bzero(otherbuf,100);
printf("请输入要发送给老爸的信息!\n");
scanf("%s",buf);
//使用写端把buf写入到第一个无名管道中
write(fd1[1],buf,strlen(buf));
//从第二个无名管道中读取内容
read(fd2[0],otherbuf,100);
printf("我老爸回复的信息是:%s\n",otherbuf);
}
}
}
有名管道单向通讯在父子进程之间通讯
#include "myhead.h"
int main()
{
int fd;
char buf[100];
//由于有名管道不能重复创建
//先判断管道文件是否存在
if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
{
//直接打开管道文件
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
else //管道文件不存在
{
//创建一个有名管道
int ret=mkfifo("/home/gec/friend",0777);
if(ret==-1)
{
perror("创建有名管道失败!\n"); //perror
return -1;
}
//再来打开
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
//创建一个子进程
pid_t id=fork();
if(id>0) //父进程
{
//从有名管道中读取内容
while(1)
{
read(fd,buf,100);
printf("儿子发送的信息是:%s\n",buf);
}
}
else if(id==0) //子进程
{
while(1)
{
bzero(buf,100);
printf("请输入要发送给父亲的信息!\n");
scanf("%s",buf);
//使用刚才打开的有名管道,把信息发送给父进程
write(fd,buf,strlen(buf));
}
}
}
两个进程没有任何血缘关系利用有名管道双向通讯
#include "myhead.h"
//p1和p2双向通信
int main()
{
int fd;
char buf[100];
char rbuf[100];
printf("p1进程运行了,是个独立的进程!\n");
//由于有名管道不能重复创建
//先判断管道文件是否存在
if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
{
//直接打开管道文件
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
else //管道文件不存在
{
//创建一个有名管道
int ret=mkfifo("/home/gec/friend",0777);
if(ret==-1)
{
perror("创建有名管道失败!\n"); //perror
return -1;
}
//再来打开
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
//循环发送信息给p2
while(1)
{
bzero(buf,100);
bzero(rbuf,100);
printf("请输入要发送给p2的信息!\n");
scanf("%s",buf);
//通过有名管道发送给p2
write(fd,buf,strlen(buf));
sleep(1);
//从管道中读取p2回复的信息
read(fd,rbuf,100);
printf("p2回复的信息是:%s\n",rbuf);
}
}
#include "myhead.h"
//双向通信
int main()
{
int fd;
char buf[100];
char rbuf[100];
printf("p2进程运行了,是个独立的进程!\n");
//由于有名管道不能重复创建
//先判断管道文件是否存在
if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
{
//直接打开管道文件
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
else //管道文件不存在
{
//创建一个有名管道
int ret=mkfifo("/home/gec/friend",0777);
if(ret==-1)
{
perror("创建有名管道失败!\n"); //perror
return -1;
}
//再来打开
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
//循环从管道中读取信息
while(1)
{
bzero(buf,100);
bzero(rbuf,100);
//通过有名管道读取p1发送的信息
read(fd,buf,100);
printf("p1发送给我的信息是:%s\n",buf);
//回复信息给p1
printf("请输入要回复给p1的信息!\n");
scanf("%s",rbuf);
write(fd,rbuf,strlen(rbuf));
sleep(1); //防止自己写的内容,自己立马读取出来了
}
}
两个没有血缘关系的进程之间利用有名管道单向通讯
#include "myhead.h"
//p1进程发送信息给p2--》单向通信
int main()
{
int fd;
char buf[100];
printf("p1进程运行了,是个独立的进程!\n");
//由于有名管道不能重复创建
//先判断管道文件是否存在
if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
{
//直接打开管道文件
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
else //管道文件不存在
{
//创建一个有名管道
int ret=mkfifo("/home/gec/friend",0777);
if(ret==-1)
{
perror("创建有名管道失败!\n"); //perror
return -1;
}
//再来打开
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
//循环发送信息给p2
while(1)
{
bzero(buf,100);
printf("请输入要发送给p2的信息!\n");
scanf("%s",buf);
//通过有名管道发送给p2
write(fd,buf,strlen(buf));
}
}
#include "myhead.h"
//p1进程发送信息给p2--》单向通信
int main()
{
int fd;
char buf[100];
printf("p2进程运行了,是个独立的进程!\n");
//由于有名管道不能重复创建
//先判断管道文件是否存在
if(access("/home/gec/friend",F_OK)==0) //说明管道文件已经存在
{
//直接打开管道文件
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
else //管道文件不存在
{
//创建一个有名管道
int ret=mkfifo("/home/gec/friend",0777);
if(ret==-1)
{
perror("创建有名管道失败!\n"); //perror
return -1;
}
//再来打开
fd=open("/home/gec/friend",O_RDWR);
if(fd==-1)
{
perror("打开管道文件失败!\n");
return -1;
}
}
//循环从管道中读取信息
while(1)
{
bzero(buf,100);
//通过有名管道读取p1发送的信息
read(fd,buf,100);
printf("p1发送给我的信息是:%s\n",buf);
}
}