管道Pipe的初次使用

来源:互联网 发布:评价成都软件技术学院 编辑:程序博客网 时间:2024/05/21 20:03
管道Pipe提供一种让多个进程间通信的方法,当进程创建管道时,每次都需要提供两个文件描述符来操作管道。其中一个对管道进行写操作,另一个对管道进行读操作。对管道的读写与一般的IO系统函数一致,使用write()函数写入数据,使用read()读出数据。

写了个例子来验证在父子进程之间管道通信效果
总结效果如下:
管道可以在多个父子进程(1个父进程,多个子进程或者多个孙子进程)通信,多管道的read操作是阻塞的,即如果管道没有别写入数据,read管道将导致进程阻塞。
当进程向管道写入数据后,读进程就会竞争,谁先读到谁就从read返回。

当然,现实应用中,在fork之后,通常在两个进程中一个关闭fd[0],一个关闭fd[1],这样来实现单向通信保证稳定性吧?

下面是我的测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

#define BUF_SIZ    32     // message buffer size

int main(int argc, char **argv)
{
    char buffer[BUF_SIZ + 1];
    int fd[2];

    // receive a string as parameter
    if ( argc != 2)
    {
        fprintf(stderr, "Usage: %s string\n", argv[0]);
        exit(1);
    }
    snprintf(buffer, BUF_SIZ, "%s", argv[1]);
    printf("\nMainT-2 %d started\n\n", getpid());
    // create pipe for communication
    if ( pipe(fd) != 0 )
    {
        fprintf(stderr, "Create pipe error: %s\n", strerror(errno));
        exit(1);
    }

    if ( fork() == 0 )     // in Child-1 process write msg to pipe
    {
        printf("Child-1 %d write to pipe\n", getpid());
        write(fd[1], buffer, strlen(buffer));
        //sleep(1);
        read(fd[0], buffer, BUF_SIZ);
        printf("Child-1 %d read: %s\n", getpid(), buffer);
        
        printf("Child-1 %d quit.\n", getpid());
        exit(0);
    }
    else     // in parent process, read msg from pipe
    {
        if ( fork() == 0 )     // in Child-2 process write msg to pipe
        {
            //close(fd[0]);
            printf("Child-2 %d write to pipe\n", getpid());
            write(fd[1], buffer, strlen(buffer));
            read(fd[0], buffer, BUF_SIZ);
            printf("Child-2 %d read: %s\n", getpid(), buffer);
            
            printf("Child-2 %d quit.\n", getpid());
            exit(0);
        }

        printf("Parent %d try read from pipe\n", getpid());
        read(fd[0], buffer, BUF_SIZ);
        printf("Parent %d read: %s\n", getpid(), buffer);
        
        printf("Main %d quit.\n\n", getpid());
    }
    return 0;
}

上面在Ubuntu 14.04编译运行结果:

ubuntu@VM-146-250-ubuntu:~$ ./a.out "ADFDFDF"

MainT-2 14793 started

Parent 14793 try read from pipe
Child-2 14795 write to pipe
Child-2 14795 read: ADFDFDF
Child-2 14795 quit.
Child-1 14794 write to pipe
Child-1 14794 read: ADFDFDF
Child-1 14794 quit.

Parent 被read阻塞

------------------------------------------------------------------------------
如果把sleep函数的注释去掉,运行结果
ubuntu@VM-146-250-ubuntu:~$ ./a.out "ADFDFDF"

MainT-2 14934 started

Parent 14934 try read from pipe
Child-2 14936 write to pipe
Parent 14934 read: ADFDFDF
Main 14934 quit.

Child-1 14935 write to pipe
Child-2 14936 read: ADFDFDF
Child-2 14936 quit.
主进程read返回后整个程序自动结束了


0 0
原创粉丝点击