进程间通信之管道
管道(无名管道)
无名管道的创建和使用函数
头文件#include <unistd.h>
函数int pipe(int filedes[2]);
int pipe(int filedes[2]);
功能:经由参数 filedes 返回两个文件描述符
参数:
filedes 为 int 型数组的首地址,其存放了管道的文件描述符 fd[0]、 fd[1]。
filedes[0]为读而打开, filedes[1]为写而打开管道, filedes[0]的输出是 filedes
[1]的输入。
返回值:成功返回0,失败返回-1
实例
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd[2];
pid_t pid;
pipe(fd);//创建管道放到 fork 之前
pid = fork();
if(pid < 0)
perror("");
else if(pid == 0)
{
sleep(3);
//fd[1]是写端
write(fd[1],"hello",5);
}
else
{
close(fd[1]);
//fd[0] 读端
while(1){
char buf[256]="";
sleep(1);
read(fd[0],buf,sizeof(buf));
printf("[%s]\n",buf);
}
}
return 0;
}
半双工
只能一端写一端读
数据先进先出
管道所传送的数据是无格式的,这要求管道的读 出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等
不是普通文件,只存在内存中
管道在内存中对应 一个缓冲区不同的系统其大小不一定相同
数 据一旦被读走,释放空间写更多的数据
管道没有 名字,只能在具有公共祖先的进程之间使用
读写特点
默认用 read 函数从管道中读数据是阻塞的
调用 write 函数向管道里写数据,当缓冲区已满时 write 也会阻塞
通信过程中, 读端口全部关闭后,写进程向管道内写数据时,写进程会(收到 SIGPIPE 信号) 退出。
从管道中读数据的特点 编程时可通过 fcntl 函数设置文件的阻塞特性。 设 置为阻塞: fcntl(fd, FSETFL, 0); 设置为非阻塞: fcntl(fd, FSETFL, O_NONBLOCK)
有名管道
有名管道创建和使用
头文件#include <sys/types.h> #include <sys/stat.h>
函数int mkfifo( const char *pathname, mode_t mode);
参数:
pathname: FIFO 的路径名+文件名。
mode: mode_t 类型的权限描述符。
返回值:成功返回0,失败:如果文件已经存在,则会出错且返回-1。
实例
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc, const char *argv[])
{
int ret=mkfifo("./fifo",0666);
if(ret<0)
perror("mkfifo:");
int fd=open("./fifo",O_RDONLY);
if(fd<0)
perror("open:");
printf("read only\n");
return 0;
}
半双工
数据遵循先入 先出的规则
FIFO 所传送的数据是无格式的,这要求 FIFO 的读出方与写入方 必须事先约定好数据的格式,如多少字节算一个消息
FIFO 在文件系统中 作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中
管道在内存 中对应一个缓冲区。不同的系统其大小不一定相同
数 据一旦被读走,释放空间写更多的数据
当使用 FIFO 的进程退出后, FIFO 文件将继续保存在文件系统中以便以后使用
FIFO 有名字,不相关的进程可以通过打开命名管道进行通信
有名管道读写的特点
系统调用的 I/O 函数都可以作用于 FIFO,如 open、 close、 read、 write 等。
打开 FIFO 时,open 没有位或 O_NONBLOCK
open 以只读方式打开 FIFO 时,要阻塞到某个进程为写而打开此 FIFO
open 以只写方式打开 FIFO 时, 要阻塞到某个进程为读而打开此 FIFO
open 以只读、只写方式打开 FIFO 时 会阻塞,调用 read 函数从 FIFO 里读数据时 read 也会阻塞
通信过程中若写 进程先退出了,则调用 read 函数从 FIFO 里读数据时不阻塞;若写进程又重新运 行,则调用 read 函数从 FIFO 里读数据时又恢复阻塞
通信过程中,读进程退 出后,写进程向命名管道内写数据时,写进程也会(收到 SIGPIPE 信号)退出
调用 write 函数向 FIFO 里写数据,当缓冲区已满时 write 也会阻塞。
打开 FIFO 时,open 位或 O_NONBLOCK
先以只读方式打开:如果没有进程 已经为写而打开一个 FIFO, 只读 open 成功,并且 open 不阻塞
先以只写方式 打开:如果没有进程已经为读而打开一个 FIFO,只写 open 将出错返回-1
read、 write 读写命名管道中读数据时不阻塞
通信过程中,读进程退出后, 写进程向命名管道内写数据时,写进程也会(收到 SIGPIPE 信号)退出
注意: open 函数以可读可写方式打开 FIFO 文件时的特点: 1、 open 不阻塞。 2、调用 read 函数从 FIFO 里读数据时 read 会阻塞。 3、调用 write 函数向 FIFO 里写数据, 当缓冲区已满时 write 也会阻塞。