Linux如何在多个进程间进行数据共享
1、有血缘关系的进程间通信是比较容易的,主要使用匿名管道(pipe)来进行
以下为pipe函数的头文件和声明:
#include <unistd.h>
int pipe(int pipefd[2]);
解释:传入一个长度为2的空int数组来存储生成管道的读与写文件描述符,如果创建管道失败则返回值为-1
2、下面以一个实例来详解父子进程间pipe工作流程:
编译代码(我这里没有用vim,用的VS code,需要的话我在这一步下添加了VS code配置链接):
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd[2];
if (pipe(fd) == -1) //创建管道
{
perror("pipe");
exit(1);
}
pid_t id = fork();//创建进程
if (id > 0) //父进程
{
close(fd[0]);//关闭管道读端
while (1)
{
write(fd[1], (void *)"hello world",12);//向管道中写入“helloworld”
sleep(1);
}
}
else//子进程
{
close(fd[1]);//关闭管道写端
while(1)
{
char buf[20];
read(fd[0],buf,12);//从管道中读取数据
printf("id:%d %s\n",getpid(),buf);
}
}
}
3、可以看到,运行结果为每一秒子进程便输出一次id和内容
但我们并未对子进程设置任何sleep函数,出现这种状况的原因是因为pipe默认是阻塞的
创建之后的管道可以看作是一个具有阻塞属性的文件(实际上确实是利用文件描述符来操作管道的),读端只读,写端只写。可以利用标准库中的read和write进行操作
4、兄弟进程间也可以用匿名管道进行通信:
例如:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd[2];
if (pipe(fd) == -1) //创建管道
{
perror("pipe");
exit(1);
}
int count;
pid_t id[2];
for (count = 0; count < 2; count++)
{
id[count]=fork();
if(id[count]==0){
break;
}
}
if (count==0) //子进程1
{
close(fd[0]);//关闭管道读端
while (1)
{
write(fd[1], (void *)"hello world",12);//向管道中写入“helloworld”
sleep(1);
}
}
else if(count==1)//子进程2
{
close(fd[1]);//关闭写端
while(1)
{
char buf[20];
read(fd[0],buf,12);//从管道中读取数据
printf("id:%d %s\n",getpid(),buf);
}
}
else//父进程
{
wait(NULL);
wait(NULL);
}
}
5、可以看到,运行结果与父子进程间通信基本不变,可以证明,兄弟间进程通信依然可以使用匿名管道。
6、没有血缘关系的进程通信时比较麻烦,实际应用中使用有名管道(mkfifo)通信较多
如果说匿名管道通信是可以看成文件的话,不如说有名管道通信就是文件,两个没有血缘关系的进程建立通信就是靠这个文件。
以下为mkfifo的函数声明和头文件:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
7、下面以一个实例来详解没有血缘关系的进程间fifo工作流程:
编译代码:
1.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
if(mkfifo("data",0666)==-1){
perror(mkfifo);
exit(1);
}
int fd=open("data",O_WRONLY);
while(1){
write(fd,(void*)"hello world",12);
sleep(1);
}
}
2.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd=open("data",O_RDONLY);
while(1){
char buf[20];
read(fd,buf,12);
printf("id:%d %s\n",getpid(),buf);
}
}
8、分别运行利用两个源代码编译的文件a和b,可以看到,虽然是两个没有血缘关系的进程,其依然可以实现通信