管道

xiaoxiao2021-02-28  91

管道(上)

管道(上) 为什么需要管道what is 管道(pipe)几种特殊情况总结

为什么需要管道

每一个进程在正常情况下都有自己的地址空间(address speace),这样的好处是让进程运行具有独立性,且凡是由进程编写的程序,该进程的稳定性好,(一个进程在自己的地址空间内运行,当他不小心崩溃了他也不会影响到其他进程),但这也是他的缺点,当我们想让一个进程给另一个进程发送数据时,我们就需要进程间通信的知识了,本文就来讲讲进程通信的管道。

进程间通信:让不同进程看到同一份公共资源,这里的公共资源不属于某一个特定的进程,他一般是由独立的第三方提供(内核)。不明白?看看下面的图

进程1将自己的有效数据写入到操作系统的缓冲区里,在通过进程2从系统的缓冲区里读出来。

what is 管道(pipe)

管道是一种最基本的IPC(InterProcess Communication-进程间通信)机制,由pipe函数创建

#include <unistd.h> int pipe(int pipefd[2]); #define _GNU_SOURCE #include <unistd.h> int pipe2(int pipefd[2], int flags);

pipefd[2]:一个具有两个整形元素的一位数组,当调用函数时,该一维数组会退化成一个指向一位数组的指针,是一个输出型参数。为什么会有两个元素呢而且还有关键字fd

当一个进程调用pipe时,它的本质是当前进程分别以读和写打开一个文件(pipe)此时这个文件打开了两次,打开一个文件就会有一个fd(文件描述符),这里分别以读和写打开pipe文件就会得到两个fd,现在明白pipefd[2]了吧。还不明白?好吧!

一个进程调用pipe就会得到一个以读方式一个以写方式打开pipe的文件文件描述符,而pipefd恰好是一个二维数组他恰好可以放两个元素,这个数组希望用0号和1号返回打开的文件,所以调用完pipe我们会得到两个文件描述符,其中0号内容表示以读方式打开,1号表示以写方式打开。

fork()后父子进程发生写时拷贝,都同时以读写方式打开了一个文件,现在终于让两个独立的进程看到一块儿公共的资源。

现在我们如果想让子进程写而让父进程读因该怎么样做?  回答正确:只要让父进程fclose(pipefd[1]),子进程fclose(pipefd[0]),这时我们就建立单向通信

#include <stdio.h>#include <unistd.h>#include <string.h>int main(){ int fds[2]; if (pipe(fds) < 0){//创建管道失败 perror("pipe"); return 1; } pid_t id = fork(); if (id == 0){//child ->write close(fds[0]); const char* msg = "hello father, I am child, hello pipe!"; while (1){ write(fds[1], msg, strlen(msg)); sleep(1); } }else{//father ->read close(fds[1]); char buf[1024]; while(1){ ssize_t s = read(fds[0], buf, sizeof(buf)-1); if (s > 0){ buf[s] = 0; printf("client->father : %s\n",buf); } } } return 0;}

运行结果:你会发现每隔一秒就打印一条”msg”。

几种特殊情况

在不关闭写端的情况下,如果写端不写了,读端会一直读,直到把缓冲区里的数据一直读完,读端会等待写端继续再写。在不关闭读端的情况下,如果读端不读了,写端一直在写,直到将缓冲区写满,写端等待读端将数据读走后再继续写。如果将读端关掉,写端同时也会关闭。如果将写端关闭,读端会将缓冲区的数据全部读完,最终他将读到文件结尾'0'值。

总结

管道的五个特点

管道只能进行单向通信。管道只能让有血缘关系的进程实现进程间通信(因为要发生写时拷贝),常用于父子进程,兄弟进程,爷孙进程。管道在读写过程自带同步机制。管道提供面向字节流的通信方式。管道随与之相关进程的退出而随即被释放,管道生命周期岁进程。
转载请注明原文地址: https://www.6miu.com/read-84579.html

最新回复(0)