IPC-进程间通信

一、管道
1、概念

2、pipe函数
2.1pipe介绍

2.2 pipe代码示例 父进程向子进程写数据
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int pfd[2]; //定义两个文件描述符,放在数组中
int ret=pipe(pfd); //定义管道
if(ret==-1)
{
perror("pipe error:");
exit(1);
}
pid=fork();
if(pid==-1)
{
perror("fork error:");
exit(1);
} else if(pid==0)
{
close(pfd[1]); //关闭子进程写端口
char buf[1024]={0};
int ret=read(pfd[0],buf,sizeof(buf)); //从管道读数据
write(STDOUT_FILENO,buf,ret);
}else
{
close(pfd[0]); //关闭父进程读端口
write(pfd[1],"hello world
",sizeof("hello world")); //向管道写数据
}
return 0;
}
2.3管道读写行为

2.4管道优劣

2.5 FIFO(有名管道)
2.5.1 FIFO概念

2.5.2实现FIFO进程通信,可以实现无血缘关的进程通信
//写端程序
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
int main()
{
//当前目录有一个myfifo文件
//打开fifo文件
int fd=open("myfifo",O_WRONLY);
//写
char buf[256]={0};
int num=1;
while(1)
{
memset(buf,0x00,sizeof(buf));
sprintf(buf,"newdata%d",num++);
write(fd,buf,sizeof(buf));
sleep(1);
//循环写
}
//关闭描述符
close(fd);
return 0;
}
//读端程序
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<unistd.h> #include<fcntl.h> int main() { int fd=open("myfifo",O_RDONLY); char buf[256]={0}; int ret; while(1) { ret=read(fd,buf,sizeof(buf)); if(ret>0) { printf("%s ",buf); } } close(fd); return 0; }
二、共享存储映射
1.创建内存映射

2.释放映射区

3.代码示例 通过mmap修改文件内容
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<string.h>
int main()
{
int fd=open("mem.txt",O_RDWR);
//创建映射
char *mem=mmap(NULL,8,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//PRIVATE 不修改文件
//char *mem=mmap(NULL,8,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);
if(mem==MAP_FAILED)
{
perror("mmap error");
return 0;
}
//拷贝数据
strcpy(mem,"i am you");
//释放mmap
munmap(mem,8);
close(fd);
return 0;
}
4.mmap注意事项

5.mmap实现父子进程间通信
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
int main()
{
//创建映射区
int fd=open("mem.txt",O_RDWR);
int *mem=mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(mem==MAP_FAILED)
{
perror("mmap error:");
return 0;
}
//fork子进程
pid_t pid=fork();
//父进程和子进程交替修改数据
if(pid==0)
{
//子进程
*mem=100;
printf("child,*mem=%d
",*mem);
sleep(3);
printf("child,*mem=%d
",*mem);
}
else if(pid>0)
{
//父进程
sleep(1);
printf("parent,*mem=%d
",*mem);
*mem=1001;
printf("parent,*mem=%d
",*mem);
wait(NULL);
}
munmap(mem,4);
close(fd);
return 0;
}

6.匿名映射(有血缘关系)
通过MAP_ANON和MAP_ANONYMOUS
int *mem=mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANON,-1,0);
7.mmap实现无血缘关系进程通信
//读端
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/mman.h>
typedef struct Student{
int sid;
char sname[20];
}Student;
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("./a.out filename");
return 0;
}
//open file
int fd=open(argv[1],O_RDWR);
//mmap
int length=sizeof(Student);
Student * stu=mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(stu==MAP_FAILED)
{
printf("map err:");
return 0;
}
//read data
while(1)
{
printf("sid = %d, sname = %s
",stu->sid,stu->sname);
sleep(1);
}
munmap(stu,length);
close(fd);
return 0;
}
//写端
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/mman.h>
typedef struct Student{
int sid;
char sname[20];
}Student;
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("./a.out filename
");
return 0;
}
//1.open file
int fd=open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666);
int length=sizeof(Student);
int num=1;
ftruncate(fd,sizeof(length));
//2.mmap
Student * stu=mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(stu==MAP_FAILED)
{
printf("mmap err:");
return 0;
}
//3.修改内存数据
while(1)
{
stu->sid=num;
sprintf(stu->sname,"xiaoming-%03d",num++);
sleep(1);
}
//4.释放映射区 关闭文件
munmap(stu,length);
close(fd);
return 0;
}