系统编程-进程间通信-无名管道

 

管道文件是一个特殊的文件,是由内核环形队列来实现的。

函数形式: int pipe(int fd[2]) ,无需额外调用open,但需手动调用close来关闭fd[0]和fd[1]。

功能: 该系统调用,用于创建无名管道。无名管道作用于有血缘关系的进程之间,完成数据传递。

头文件:#include <unistd.h>

参数:两个文件描述符,fd[0]是读端,fd[1]是写端

返回值: 成功返回0,出错返回-1。

 

特点:

** 管道是创建在内存中的,进程结束,空间释放,管道就不存在了。

** 管道中的数据,读完后就被删除了。

** 如果管道中没有数据可读,则会阻塞

** 如果管道被写满了,也会阻塞

 

局限性:

**数据一旦被读走,便不在管道中存在,不可反复读取。

**由于管道采用半双工通信方式。因此,数据只能在一个方向上流动

**只能在有公共祖先的进程间使用管道

 

实验1 -  实现父子进程间通信

实验思路:

1. 父进程调用pipe函数创建无名管道,得到两个文件描述符fd[0]、fd[1]指向管道的读端和写端。

2. 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。

3. 父进程关闭管道读端,子进程关闭管道写端。(这才是正确操作,只留一个入口,一个出口,这样才能保证数据只在一个方向上流动)

 父进程可以向管道中写入数据,子进程将管道中的数据读出。

    由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信。

实验代码:

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
 
void sys_err(const char *str)
{
    perror(str);
    exit(1); 
}
 
int main(void)
{
    pid_t pid;
    char buf[1024];
    int fd[2];
     
    char *p = "test for pipe\n";
 
    if (pipe(fd) == -1)
        sys_err("pipe");
 
    pid = fork();
    if (pid < 0) {
        sys_err("fork err");
     
    }else if (pid == 0) {
        close(fd[1]);
        int len = read(fd[0], buf, sizeof(buf));
        write(STDOUT_FILENO, buf, len);
        close(fd[0]);
     
    }else {
        close(fd[0]);
        write(fd[1], p, strlen(p));
        wait(NULL); // 不获取子进程死因,传入NULL即可。
            // 父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出。
        close(fd[1]);
    }

    return 0;
}

 

 

 

 

 

 

 

 

.

posted @ 2020-10-12 22:30  一匹夫  阅读(275)  评论(0编辑  收藏  举报