linux之进程间通道---管道

管道:管道分为无名管道(pipe)跟有名管道(fifo)

管道通信过程:

进程A向管道中写数据,进程B从管道中读数据。读,写操作都是以阻塞方式。

无名管道:

特点:

1.只能用于具有亲缘关系(父子进程/兄弟进程)进程间通信

2.只能以半双工方式通信,且读 写端固定

3.可以将管道看成一种特殊文件,对管道读写就像对普通文件读写一些,只是它是以阻塞方式读写的。无名管道在本质上是一块内存缓冲区

创建无名管道函数:

int pipe(int fd[2])

参数:

      当创建成功,返回对管道读写文件描述符,fd[0]读文件描述符,fd[1]|写文件描述符

返回值:

      成功: 返回 0

      失败:  返回-1  设置errno

注意:在利用fork/vfork创建子进程之前,创建无名管道

原因:用pipe创建无名管道后返回对这个管道读写文件描述符fd[2],在fork后,操作系统会复制fd[2]给子进程,子进程也就拥有了对这个管道的读写操作。

这也是为什么无名管道只适用有血缘关系进程间通信。

//*******************************************************************************************************************************

子进程向管道中写数据,父进程读管道数据,并向终端输出:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
int main(int argc,char** argv)
{
    int fd[2];
    pid_t pid;

    int ret=pipe(fd);//创建无名管道
    if(ret<0)//创建失败
    {
        perror("pipe error\n");
        exit(1);
    }
    pid=fork();
    if(pid<0)//创建子进程失败
    {
        perror("fork error\n");
        close(fd[0]);
        close(fd[1]);
        exit(1);
    }else if(pid==0)//子进程返回
    {
        close(fd[0]);//关闭读端文件描述符
        char buff[1024]="this is pipe test";
        write(fd[1],buff,strlen(buff));
        close(fd[1]);//关闭写端文件描述符
    }else//父进程返回
    {
        close(fd[1]);
        char buff[1024];
        int count=read(fd[0],buff,1024);
        if(count<0)//读管道数据失败
        {
            perror("parent process read error\n");
            close(fd[0]);
            exit(1);
        }
        buff[count]='\0';
        printf("receive data %s\n",buff);
        close(fd[0]);
    }
    return 0;
}

实验输出:

有名管道:

特点:

1.适用于任何两个进程间进行通信

2.半双工通信方式

创建有名管道函数:

int mkfifo(const char* pathname,mode_t mode);

参数:

       pathname:有名管道的名字

       mode:当管道不存在时,创建管道文件权限

返回值:

     成功:返回0

    失败:返回-1   设置errno

//******************************************************************************

fifo_w.c:对管道fifo写数据

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/types.h>
#include<string.h>
int main(int argc,char** argv)
{
    char buff[1024];
    int ret=mkfifo("fifo",0666);//创建管道文件
    if(ret<0)//失败
    {
        perror("mkfifo error\n");
        exit(1);
    }

    int fd=open("fifo",O_WRONLY);//打开管道文件
    if(fd<0)//失败
    {
        perror("open fifo error\n");
        exit(1);
    }

    while(1)
    {
        printf("write data ");
        fgets(buff,1024,stdin);//从终端读取字符串
        write(fd,buff,1024);//写入管道
        if(strncmp(buff,"end",3)==0)//从终端输入end退出程序
            break;
    }
    close(fd);
    return 0;
}

fifo_r.c从管道读数据:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>

int main(int argc,char** argv)
{
    char buff[1024];
    int ret;
    int fd=open("fifo",O_RDONLY);//打开管道文件
    if(fd<0)
    {
        perror("open error\n");
        exit(1);
    }
    
    while(1)
    {
        ret=read(fd,buff,1024);//读管道数据
        if(ret==0)//写端关闭
            break;
        buff[ret]='\0';
        printf("read data %s",buff);
    }
    close(fd);
    return 0;
}

实验输出:左边读管道数据    右边写管道数据

猜你喜欢

转载自www.cnblogs.com/nwjlq/p/12953025.html
今日推荐