Linux基础教程:10、进程通讯(管道通讯)

进程之间是独立的,但是又是有联系的,他们可以使用管道、信号、socket、消息队列和共享内存来实现通信,那么我们先来看看进程之间如何使用管道:

​
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
​
        pid_t pid;
        int fd[2];
        int ret=pipe(fd);
        if(ret==-1)
        {
                printf("pipe error!\n");
                exit(1);
        }
        pid=fork();
        if(pid==-1)
        {
                perror("fork error\n");
                exit(1);
        }
        else if(pid>0)
        {
                        waitpid(pid,NULL,WNOHANG);
                        close(fd[1]);
                        char buf[1024]={0};
                        int len=0;
                        len=read(fd[0],buf,sizeof(buf));
                        printf("parent receive meassge:%s\n",buf);
                        close(fd[0]);
                        sleep(2);
        } 
        else if(pid==0)
        {
​
                        close(0);
                        char * str="this is a message by child send!\n";
                        write(fd[1],str,strlen(str)+1);
                        close(fd[1]);
                        sleep(2);
​
​
        }
        return 0;
}
                                            

要注意几个点,管道是需要在进程创建之前在再创建的,如果在进程之后创建管道的话顺序就乱了,管道将不会生效,而且这个半双工过程,也就说我们一次只能通信一次,要么是a向b发信息,要么就是b向a,不能ab同时,所以我这里就拿父子进程来讲解;

首先我们创建管道(pipe函数):

int fd[2];
int ret=pipe(fd);

他需要一个int数组,两个元素,一个是读端(fd[0])一个是写端(fd[1]),pipe这个函数就是用来创建管道的,他的参数就是这个数组;

close(fd[1]);
char buf[1024]={0};
int len=0;
len=read(fd[0],buf,sizeof(buf));
printf("parent receive meassge:%s\n",buf);
close(fd[0]);
sleep(2);

在我们要写或者读一个内容的时候,如果是写我们就应该把读的管道描述符关闭,也就是这里的fd[0],同理如果是读的话就是关闭写了;

使用读写流也是read和write之前我讲过的,参数的话第一个就是描述符,第二个就是数据,第三个就是长度,这里注意read的返回值是读取到的真实长度,如果读取失败的话就是返回-1;如果想要父子之间一直保持通讯的话我们就不能关闭读写流了:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
​
        pid_t pid;
    int fd[2];
    int ret=pipe(fd);
    if(ret==-1)
    {
        printf("pipe error!\n");
        exit(1);
    }
    pid=fork();
        if(pid==-1)
        {
                perror("fork error\n");
                exit(1);
        }
        else if(pid>0)
        {
        char buf[1024]={0};
        while(1)
        {
            waitpid(pid,NULL,WNOHANG);
            int len=0;
            len=read(fd[0],buf,sizeof(buf));
            printf("parent receive meassge:%s\n",buf);
            sleep(2);
            char * str = "fighing ,child ,you are my hope!\n";
            write(fd[1],str,strlen(str)+1);
            sleep(2);
        }
        }
        else if(pid==0)
        
    {
        char buf[1024]={0};
        while(1)
        {
            char * str="fighting , parent , you are my example!\n";
            write(fd[1],str,strlen(str)+1);
            sleep(2);
            int len=0;
            len = read(fd[0],buf,sizeof(buf));
            sleep(2);
            printf("child receive message:%s\n",buf);
        }
                
        }
        return 0;
}
​

父子进程之间通讯要注意:

1、要先创建管道,再创建进程;2、父子进程要互相读写数据的时候就不需要关闭读写端,卡好时间即可;

匿名管道的含义:

匿名管道就是类似于 ls | wc –l这种由| 连接的一个或者多个命令,|的前一个命令的输出会作为后一个命令的输入;

父子之间通讯是共用一个管道,管道的两端只能进行读写操作中的一种,因此父子通讯时应该关闭父子进程中的一个文件描述符,比如在父进程中写操作,在子进程中读操作时,我们就应该使用close函数关闭父进程中的读端和子进程的写端;这样就可以通过向管道中读写数据来实现进程之间的通讯;

总结一下,结合之前的父子通讯内容,我们多加了循环和管道,循环的目的是为了可以更容易的看到结果,管道就是用来父子通讯的,父子通讯时只能一个写一个读,而且要将时间拿捏得死死的才能通讯成功,如果只是通讯一次的话我们就需要在一个进程进行读/写操时关闭另一个的写/读端;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程学渣ズ

谢谢老板

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值