无名管道

一、函数原型
 #include<unistd.h>
 int  pipe(int fd[2])
功能:创建无名管道
参数: 由参数fd返回两个文件描述符,fd[0]为读而打开,fd[1]为写而打开
返回值 :成功 0  失败 -1


二、管道特性

无名管道又被称为pipe,是进程间通信的一种方式。pipe具有以下特点:

●只能用于具有血缘关系的进程之间

●半双工的通信模式,具有固定的读端和写端

●一种特殊的文件,存在于内存中。可通过read、write对其操作

因为pipe存在于内存中,所以无法像操作普通文件那样通过指定路径来打开文件。通常的做法是在父进程中创建管道,再创建子进程。由于子进程继承了父进程打开的文件描述符,所以父子进程就可以通过创建的管道进行通信。

        
         若读取管道时没有数据,则进程会被阻塞,直到有数据可读。写管道时除非管道已满,一般情况下写入操作很快会返回。

无名管道由一个在基本文件系统存储设备上的 INODE ,一个与其相连的内存 INODE ,两个打开文件控制块(分别对应管道的信息发送端和信息接收端)及其所属进程的描述信息来标识,在系统执行 PIPE P )命令行之后生成。并在 P[0] 中返回管道的读通道打开文件描述等,在 P[1] 中返回管道的写通道打开文件描述符。从结构上看,无名管道没有文件路径名,不占用文件目录项,因此文件目录结构中的链表不适用于这种文件,它只是存在于打开文件结构中的一个临时文件,随其所依附的进程的生存而生存,当进程终止时,无名管道也随之消亡
送入管道的信息一旦被读进程取用就从管道中消失了,读写操作之间符合先进先出的队列原则

三、注意事项

使用管道的注意事项:

1.       当读一个写端已关闭的管道时,在所有数据被读取之后,read函数返回值为0,以指示到了文件结束处;

2.       如果写一个读端关闭的管道,则产生SIGPIPE信号。如果忽略该信号或者捕捉该信号并处理程序返回,则write返回-1,errno设置为EPIPE

          PS:所谓的关闭,必须是全部进程都已经将读端或写端的描述符关闭,如父子进程之类的。
        
        3、   在写管道(或FIFO)是,常量PIPE_BUF规定了内核中管道缓冲区的大小,如果对管道调用write。而且要求写的字节书小于等PIPE_BUF,则此操作不会与其他进程对同一管道(或FIFO)的writr操作穿插进行,但是,若有多个进程同时写一个管道(或FIFO),而且有进程要求写的字节数超过PIPE_BUF字节数时,则写操作的数据可能互相穿插,用pathconf或fpathconf函数可以确定PIPE_BUF的值。
 当写入管道的数据小于PIPE_BUF时,write操作是一个原子操作。PIPE_BUF一般为4098
         write和read会同样使管道文件偏移量改变。但无法使用lseek定位的等

       
例程:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <error.h>

#define error_exit(_errmsg_) error(EXIT_FAILURE, errno, _errmsg_)

#define BUFF_SIZE 1024

int main()
{
int pifd[2];
pid_t pid;
char *buff = NULL;

if (-1 == pipe(pifd))
error_exit("pipe");

buff = (char *)malloc(BUFF_SIZE);

if (-1 == (pid = fork()))
error_exit("fork");

if (0 < pid) {
/* father */
close(pifd[0]);

while (1) {
fgets(buff, BUFF_SIZE, stdin);
if (!strcmp(buff, "#quit\n"))
break;
if (-1 == write(pifd[1], buff, strlen(buff)+1))
error_exit("write");
}
} else {
/* child  */
close(pifd[1]);
while (1) {
if (0 >= read(pifd[0], buff, BUFF_SIZE))
error_exit("read");
printf("<%s", buff);
}
}

close(pifd[0]);
close(pifd[1]);
free(buff);
return 0;
}


你可能感兴趣的:(linux)