linux进程间通信之管道(pipe与fifo)

/* 无名管道 */

1、概念:
   管道是linux进程间通信的一种方式,其是利用管道“文件”作为不同进程之间的传输数据的媒介,而实现进程间的数据交换。
    而无名管道pipe则是利用内核虚拟出来的管道“文件”来作为不同进程间数据传输通道,而并非实际存在真正意义上的文件。
   
    特点:
            1、 无名管道只能用于具有亲缘关系的进程之间的通信,并且要由父进程来创建。(eg:父子进程间通信)
           2、通信方式是单工的,意味着要实现两个进程间的双向通信,必须建立两个管道。
           3、 其存在于内核为其分配的内核空间在。

2、无名管道的用法:
   1、创建无名管道: pipe(int pipefd[2]);
                     该函数返回两个文件描述符:pipefd[0](指向读端),pipefd[1](指向写端)
   2、写管道数据: ssize_t write(int fd, const void *buf, size_t count);
   3 、读管道数据: ssize_t read(int fd, void *buf, size_t count);
   4、关闭管道  : int close(int fd);

3、例程如下:
/*
 * Author : zengwenzheng
 * Create time:2014-1-15
 * Description:This file is to create a noname pipe
 * and test the pipe ipc.
 */
#include
#include
#include
#include
#include
#include

/*
 * The data structure which use to be translate
 */
typedef struct student
{
    char name[20];
    char class[10];
    int age;

}student,*tystudent;

/*
 *
 */
int main(void)
{
    int pipefd[2];
    int ret = pipe(pipefd);//create a noname pipe
    if(ret < 0)//error
    {
        printf("create pipe fail !\n");
        perror("pipe error");
        exit(-1);
    }

    pid_t pid = fork(); //create child process

    if(pid > 0)//parent process write message
    {
        close(pipefd[0]);//close the read port

        tystudent stu = (tystudent)malloc(sizeof(student));
        strcpy(stu->name,"wenzheng");
        strcpy(stu->class,"class68");
        stu->age = 22;

        write(pipefd[1],stu,sizeof(student));//write data in the pipe

        sleep(1);
    }
    if(pid == 0)//child process read the pipe
    {
        close(pipefd[1]);//close the write port

        tystudent stu = (tystudent)malloc(sizeof(student));

        read(pipefd[0],stu,sizeof(student));

        printf("%s\n",stu->name);
        printf("%s\n",stu->class);
        printf("%d\n",stu->age);
    
    }
    wait(NULL);

}

/* 有名管道 */

1、概念:
   与无名管道的不同之处在于,有名管道fifo的管道文件是真正意义上的文件,其由用户自定义分配。    

    特点:
            1、 有名管道fifo可以用于任意不同进程间的通信,不仅仅局限于具有亲缘关系的进程之间。
           2、 其存储路径是用户定义的,有名管道文件是真正意义上的文件。

2、有名管道的用法:
    1、创建有名管道:
int mkfifo(const char *pathname, mode_t mode);
    2、打开管道    
int open(const char *pathname, int flags);
    3、读写、关闭有名管道与操作无名管道一致。

3、创建有名管道(mkfifo)时错误返回信息:

       EACCES One  of  the  directories in pathname did not allow search (exe‐
              cute) permission.

        EEXIST pathname already exists.  This includes the case where  pathname
              is a symbolic link, dangling or not.

       ENAMETOOLONG
              Either the total length of pathname is greater than PATH_MAX, or
              an individual filename  component  has  a  length  greater  than
              NAME_MAX.  In the GNU system, there is no imposed limit on over‐
              all filename length, but some file systems may place  limits  on
              the length of a component.

       ENOENT A  directory  component  in pathname does not exist or is a dan‐
              gling symbolic link.

    以上只列出几种,其中需要稍加注意第2种,其用于判断创建的管道是否已经存在。
4、例程如下:聊天程序(客户端)
/*
* Filename : client.c
* Author : zengwenzheng
* Create time : 2014-1-15
* Description : This file is to create two namepipe
* the one is used to send message(child process),
* the other is used to receive message(parent process).
*/

#include
#include
#include
#include
#include
#include
#include
#include


int main(void)
{    
    
    pid_t pid = fork();//create process

    /* parent process */
    if( pid > 0)
    {
        int ret = 0;
        /* create name pipe2 */
        ret = mkfifo("pipe2",0777);
        if(( ret < 0)&&(errno != EEXIST))//create pipe2 fail
        {
            perror("mkfifo pipe2");
            exit(-1);
        }
        
        /* read data from pipe2 */
        int pipefd2 = open("pipe2",O_RDONLY);
        if(pipefd2 < 0)//open error
        {
            printf("open pipe2 error !\n");
            exit(-1);
        }

        char buffer[100];
        while(1)
        {
            bzero(buffer,sizeof(buffer));
            /* read data from pipe2 */
            int num = read(pipefd2,buffer,sizeof(buffer));
            if(num!=0)
            {
                printf("%s\n",buffer);
            }
        }

    }
    /* child process */
    if(pid == 0)
    {
        int ret = 0;
        /* create namepipe */
        ret = mkfifo("pipe",0777);
        if( (ret < 0)&&(errno != EEXIST))//create pipe fail
        {
            perror("create pipe");
            exit(-1);
        }
        /* open namepipe by write */
        int pipefd = open("pipe",O_WRONLY);
        if(pipefd < 0) //open fail
        {
            printf("open pipe2 error !\n");
            exit(-1);
        }

        char buffer[100];
        while(1)
        {
            /* write into pipe */
            bzero(buffer,sizeof(buffer));//clear buffer
            scanf("%s",buffer);
            write(pipefd,buffer,100);                
        }    
    }
}



你可能感兴趣的:(Linux)