进程间通信——管道

原创 2018年04月15日 10:54:54

一、进程间通信的目的

    1.数据传输:一个进程需要将它的数据发送给另一个进程。

    2.资源共享:多个进程之间共享同样的资源。

    3.通知事件:一个进程需要给另一个或是一组进程发送消息,通知它们发生了某种事件,(比如进程终止时要通知父进程)。

    4.进程控制:有些进程希望控制另一个进程,此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。


二、什么是管道

    1.管道是Unix中最古老的进程间通信的形式。

    2.我们把从一个进程到另一个进程的一个数据流成为“管道”。


三、管道的分类

    1.匿名管道

    2.命名管道


 匿名管道是在函数中实现的,没有直接命令,而且要清楚文件描述符表中的0,1,2号下标对应的是stdin,stdout,stderror.

#include<unistd.h>
功能:创建一无名管道
原型:
int pipe(int fd[2]);
参数:fd:文件描述符数组,fd[0]:读端,fd[1]:写端。返回值:成功为0;失败返回错误码。

以下是一个从键盘中读入数据,然后写入管道,在读取管道,写到屏幕的代码实现。仅供参考:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main()
{
    int fds[2];
    char buf[128];
    int len;
    if(pipe(fds) == -1)
    {
        perror("make pipe");//创建失败
        exit(1);
    }
    while(fgets(buf,128,stdin))
    {
        len = strlen(buf);
        //write into pipe
        if(write(fds[1],buf,len) != len)
        {
            perror("write to pipe");
            break;
        }
        memset(buf,0x00,sizeof(buf));
        //read from pipe
        if(len = read(fds[0],buf,128) == -1)
        {
            perror("read from pipe");
            break;
        }
        //write to stdout
        if(write(1,buf,len) != len)
        {
            perror("write to stdout");
            break;
        }
    }

    return 0;
}

其中有几个系统调用,

char *fgets(char *s, int size, FILE *stream);
  ssize_t write(int fildes, const void *buf, size_t nbyte);
   ssize_t read(int fildes, void *buf, size_t nbyte);


如果用fork来实现共享管道:




如果这个看不懂的话,没关系,再来有一个简单的,




来看一下代码的实现,

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>


#define ERR_EXIT(m)\
        do\
        {\
        perror(m);\
        exit(EXIT_FAILURE);\
        }while(0)


int main(int argc,char* argv[])
{
    int pipefd[2];
    if(pipe(pipefd) == -1)
    {
        ERR_EXIT("pipe error");
    }

    pid_t pid = fork();
    if(pid == -1)
    {
        ERR_EXIT("fork error");
    }
    if(pid == 0)
    {
        close(pipefd[0]);//关闭子进程的读端
        write(pipefd[1],"helloworld",10);
        close(pipefd[1]);
        exit(EXIT_SUCCESS);
    }

    close(pipefd[1]);//关闭父进程的写端
    char buf[11] = {0};
    read(pipefd[0],buf,11);
    printf("buf = %s\n",buf);
    return 0;
}

命名管道:

    命令行输入 mkfifo filename

    也可以在程序中创建:

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

    匿名管道和命名管道的区别只在于它们的创建与打开方式不同,匿名管道(pipe创建并打开),命名管道(open打开)。

下面用命名管道实现文件拷贝:

读取文件。写入命名管道。

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

#define ERR_EXIT(m)\
        do\
        {\
        perror(m);\
        exit(EXIT_FAILURE);\
        }while(0)

int main()
{
    mkfifo("tp",0644);
    int infd = open("abc",O_RDONLY);
    if(infd == -1)
    {
        ERR_EXIT("open");
    }
    int outfd = open("tp",O_WRONLY);
    if(outfd == -1)
    {
        ERR_EXIT("open");
    }
    char buf[1024];
    int n;
    while((n = read(infd,buf,1024)) > 0)
    {
        write(outfd,buf,n);
    }
    close(infd);
    close(outfd);
    
    return 0;
}


读取管道,写入目标文件:

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

#define ERR_EXIT(m)\
        do\
        {\
        perror(m);\
        exit(EXIT_FAILURE);\
        }while(0)

int main()
{
    int outfd = open("abc.bak",O_WRONLY|O_CREAT|O_TRUNC,0644);
    if(outfd == -1)
    {
        ERR_EXIT("open");
    }
    int infd = open("tp",O_RDONLY);
    if(infd == -1)
    {
        ERR_EXIT("open");
    }
    char buf[1024];
    int n;
    while((n = read(infd,buf,1024)) > 0)
    {
        write(outfd,buf,n);
    }
    close(infd);
    close(outfd);
    unlink("tp");
    
    return 0;
}

在看一个管道间的相互通信吧。

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


#define ERR_EXIT(m)\
        do\
        {\
        perror(m);\
        exit(EXIT_FAILURE);\
        }while(0)



int main()
{
    umask(0);//设置权限
    if(mkfifo("mypipe",0644) < 0)
    {
        ERR_EXIT("mkfifo");
    }
    int rfd = open("mypipe",O_RDONLY);
    if(rfd < 0)
    {
        ERR_EXIT("open");
    }
    
    char buf[1024];
    while(1)
    {
        buf[0] = 0;
        printf("please wait...\n");
        ssize_t s = read(rfd,buf,sizeof(buf)-1);//没有回车字符
        if(s > 0)
        {
            buf[s-1] = 0;
            printf("client say:%s\n",buf);
        }
        else if(s == 0)
        {
            printf("client quit,exit now!\n");
            exit(EXIT_SUCCESS);
        }
        else
        {
            ERR_EXIT("read");    
        }
    }
    close(rfd);
    return 0;
}

client.c

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


#define ERR_EXIT(m)\
        do\
        {\
        perror(m);\
        exit(EXIT_FAILURE);\
        }while(0)



int main()
{
    int wfd = open("mypipe",O_WRONLY);
    if(wfd < 0)
    {
        ERR_EXIT("open");
    }
    
    char buf[1024];
    while(1)
    {
        buf[0] = 0;
        printf("please Enter...\n");
        fflush(stdout);
        ssize_t s = read(0,buf,sizeof(buf)-1);//没有回车字符
        if(s > 0)
        {
            buf[s] = 0;
            write(wfd,buf,strlen(buf)); 
        }
        else
        {
            ERR_EXIT("read");    
        }
    }
    close(wfd);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DuckyLoser/article/details/79946661

进程间的通信方式——pipe(管道)

详解进程间通信方式———管道;管道是如何实现进程间通信的;以及管道读取数据的四种方式,以及管道容量的大小。...
  • skyroben
  • skyroben
  • 2017-05-10 00:43:13
  • 7089

Python下的进程间通信-管道

背景:在python下利用subprocess模块实现进程间的通信。 使用subprocess包中的函数创建子进程的时候,要注意: 1) 在创建子进程之后,父进程是否暂停,并等待子进程运行。 2...
  • ljp1919
  • ljp1919
  • 2017-03-25 18:30:20
  • 1083

进程间通信之管道篇

何为进程间通信 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都是看不到的。所以进程之间如果要交换数据就必须通过内核。 在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核...
  • qq_33724710
  • qq_33724710
  • 2016-08-28 14:22:55
  • 806

进程间通信:管道(pipe)

管道的概述 管道也叫无名管道,它是是 UNIX 系统 IPC(进程间通信) 的最古老形式,所有的 UNIX 系统都支持这种通信机制。 无名管道有如下特点: 1、半双工...
  • lianghe_work
  • lianghe_work
  • 2015-08-16 23:19:43
  • 4703

进程间通信:管道及命名管道(代码实现)

管道:1.管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;             2.只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);             3...
  • wangiijing
  • wangiijing
  • 2016-07-07 21:03:31
  • 2797

【Linux】进程间通信之管道

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数...
  • Scenlyf
  • Scenlyf
  • 2016-07-25 21:05:51
  • 1136

进程间通信方式总结——管道(一)

Linux/Unix系统IPC是各种进程间通信方式的统称,但是其中极少能在所有Linux/Unix系统实现中进行移植。随着POSIX和Open Group(X/Open)标准化的推进呵护影响的扩大...
  • tf_apologize
  • tf_apologize
  • 2017-04-13 16:28:47
  • 555

孙鑫vc++ 17 进程间通信(3) 命名管道

一、基础知识 1.命名管道 (1)命名管道是围绕Windows文件系统设计的一种机制,采用“‘命名管道文件系统’(Named Pipe File System,NPFS)“接口 (2)命名管道通...
  • wang_cong0214
  • wang_cong0214
  • 2013-01-07 13:51:49
  • 2928

进程间通信-管道(PIPE)和有名管道(FIFO)

前面我们学习了一下进程,我们知道多,进程间的地址空间相对独立。进程与进程间不能像线程间通过全局变量通信。 如果想进程间通信,就需要其他机制。          常用的进程间通信方式有这...
  • w616589292
  • w616589292
  • 2016-03-22 18:52:34
  • 2749

Linux进程间通信——使用命名管道

在前一篇文章——Linux进程间通信——使用匿名管道中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程...
  • ljianhui
  • ljianhui
  • 2013-08-23 00:10:31
  • 67432
收藏助手
不良信息举报
您举报文章:进程间通信——管道
举报原因:
原因补充:

(最多只允许输入30个字)