golang父进程通过管道向子进程传递数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang父进程通过管道向子进程传递数据相关的知识,希望对你有一定的参考价值。

参考技术A golang父进程通过管道向子进程传递数据

这里例子里面父进程launch一个子进程,然后通过管道(stdin)向子进程传递文本串。

父进程:

子进程:

进程间通信

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\\n",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\\n",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\\n",*mem);
                        sleep(3);
                printf("child,*mem=%d\\n",*mem);

        
        else if(pid>0)
        
                //父进程
                sleep(1);
                printf("parent,*mem=%d\\n",*mem);
                *mem=1001;
                printf("parent,*mem=%d\\n",*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 \\n",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\\n");
                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;

以上是关于golang父进程通过管道向子进程传递数据的主要内容,如果未能解决你的问题,请参考以下文章

管道通信为啥比共享内存效率低

进程通信——管道消息队列共享内存信号量

父组件向子组件传递数据

使用命名管道向子进程发送参数

通过管道从多个子进程写入父进程

将字符串发送到子进程的信号