zoukankan      html  css  js  c++  java
  • 进程间通信(管道和有名管道)

    管道(Pipe)是两个进程之间进行单向通信的机制,因为它的单向性,所以又称为半双工管道。它主要用于进程间的一些简单通信。

    1. 数据只能由一个进程流向另一个进程(一个写管道,一个读管道);如果要进行全双工通信,需要建立两个管道。
    2. 管道只能用于父子进程或者兄弟进程之间的通信。
    3. 管道没有名字,且其缓冲区大小有限。
    4. 一个进程向管道写数据,数据每次都添加在管道缓冲区的末尾;另一个进程从管道另一端读数据,从缓冲区头部读出数据。

    创建管道的命令:

    #include <unistd.h>
    int pipe(int fd[2])

    管道两端分别用描述符fd[0]和fd[1]来描述。其中fd[0]只能用于读,称为管道读端;fd[1]只能用于写,称为管道写端。
    管道的一般用法:先创建一个管道,之后用fork创建一个子进程,之后父进程关闭管道的读端(或写端),子进程关闭管道的写端(或读端),父进程向管道写输入,子进程就能从管道读数据了。

    例子:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
     
    /*读管道*/
    void read_from_pipe (int fd)
    {
            char message[100];
            read (fd,message,100);
            printf("read from pipe:%s",message);
    }
     
    /*写管道*/
    void write_to_pipe (int fd)
    {
            char *message = "Hello, pipe!
    ";
            write (fd, message,strlen(message)+1);
    }
     
    int main(void)
    {
            int     fd[2];
            pid_t   pid;
            int     stat_val;
     
            if (pipe (fd))
            {
                    printf ("create pipe failed!
    ");
                    exit (1);
            }
     
            pid = fork();
            switch (pid)
            {
                    case -1:
                            printf ("fork error!
    ");
                            exit (1);
                    case 0:
                            /*子进程关闭fd1*/
                            close (fd[1]);
                            read_from_pipe (fd[0]);
                            exit (0);
                    default:
                            /*父进程关闭fd0*/
                            close (fd[0]);
                            write_to_pipe (fd[1]);
                            wait (&stat_val);
                            exit (0);
            }
     
            return 0;
    }

    有名管道

    管道的一个不足之处是没有名字,因此只能在具有亲缘关系的进程之间通信。而“有名管道”与此不同,它提供了一个路径名与之关联,作为一个设备文件存在,即使无亲缘关系的进程之间,只要能访问该路径,也可以通过FIFO进行通信。FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。

    函数原型:

    #include <sys/types.h>
    #include <sys/stat.h>
    int mkfifo(const char *path,mode_t mode);

    path为创建有名管道的路径名;mode为创建有名管道的模式,指明其存取权限。函数调用成功返回0,失败返回-1。
          使用一个存在的有名管道之前,需要用open()将其打开。因为有名管道是一个存在于硬盘上的文件,而管道是存在于内存中的特殊文件。

          以下程序演示有名管道在无亲缘关系的进程之间如何通信。

    写端:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
     
    #define FIFO_NAME    "myfifo"
    #define BUF_SIZE    1024
     
    int main(void)
    {
        int     fd;
        char    buf[BUF_SIZE] = "Hello procwrite, I come from process named procread!";
     
        umask(0);
        //指明创建一个有名管道且存取权限为0666,即创建者、与创建者同组的用户、其他用户对该有名管道的访问权限都是可读可写
        if (mkfifo (FIFO_NAME, S_IFIFO | 0666) == -1)        
        {
            perror ("mkfifo error!");
            exit (1);
        }
     
        if((fd = open (FIFO_NAME, O_WRONLY) ) == -1)/*以写方式打开FIFO*/
        {
            perror ("fopen error!");
            exit (1);
        }
        write (fd, buf, strlen(buf)+1); /*向FIFO写数据*/
     
        close (fd);
        exit (0);
    
    }

    读端:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/types.h>
     
    #define FIFO_NAME      "myfifo"
    #define BUF_SIZE        1024
     
    int main(void)
    {
            int     fd;
            char    buf[BUF_SIZE];
     
            umask (0);
            fd = open(FIFO_NAME, O_RDONLY);
            read (fd, buf, BUF_SIZE);
            printf ("Read content: %s
    ", buf);
            close (fd);
            exit (0);
    }

    以上就是管道和有名管道的基本用法了。

  • 相关阅读:
    使用KNN算法手写体识别
    os内置模块
    python步长为负时的情况
    qplot()函数的详细用法
    python文件I/O
    python中 @property
    python中定制类
    python中多重继承与获取对象
    python继承,判断类型,多态
    python中访问限制
  • 原文地址:https://www.cnblogs.com/lonelamb/p/11261122.html
Copyright © 2011-2022 走看看