管道通信分为无名管道和有名管道,无名管道可以用于具有亲缘关系进程间的通信,有名管道克服管道没有名字的限制
管道是Linux支持的最初UNIX IPC形式之一,具有以下特点
- 管道是半双工的,数据只能想一个方向流动,需要进行双向通讯时需要建立两个管道
- 只能用与父子进程和兄弟进程之间(具有亲缘关系)的通讯
- 单独构成一种独立的文件系统,管道对于管道两端的进程来说就是两个文件,但是它不是普通文件,也不是系统文件,而是一种独立文件
- 数据的读出和写入,一个进程箱管道中写的内容从管道的另一端读出,写入的内容每次都添加在管道缓冲区的末尾,并且每次都从管道的缓冲区头部读出
建立无名管道
pipe函数用于建立管道
表头文件 | #include |
---|---|
函数定义 | int pipe(int filedes[ ] |
函数说明 | pipe()会建立管道,并将文件描述符由参数filedes数组返回,filedes[0]为管道的读取端,filedes[1]为管道的写入端 |
-返回值- | 成功返回0,错误返回-1,并将错误原因存于error中 |
例如
#include<stdio.h>
#include<unistd.h>
int main()
{
int filedes[2];
char buf[80];
pipe(filedes);
if (fork() > 0)
{
char s[] = "hello!\n";
write(filedes[1],s,sizeof(s));
}
else
{
read(filedes[0],buf,80);
printf("%s",buf);
}
return 0;
}
管道用于不同进程间的通讯,通常现场见一个管道,然后再通过fork()函数,创建一个子进程,然后子进程会继承父进程所创建的管道
读取无名管道
管道两端可分别用描述符fd[0]和fd[1]来描述,fd[0]只能读,fd[1]只能写,
从管道中读取数据
- 如果管道的写端不存在,则认为已经读到管道末尾,返回读出的字节数为0
- 当管道的写端存在时,如果请求的字节数大于PIPE_BUF,则返回现有的字节数,数目不大于PIPE_BUF,则返回管道中现有的字节数,
关于管道中读取规则的验证
创建有名管道
无名管道最大的限制是只能用于具有亲缘关系的进程间通信,在有名管道提出后,这个限制得到克服,它提供了一个路径名与之相关,以FIFO的文件形式存在于文件系统中,
这样即使与FIFO创建进程不存在亲缘关系的进程,只要可以访问该路径,那么就能与之通信
mkfifo函数用于创建有名函数
表头文件 | #include<sys/stat.h>——#include<sys/types.h> |
---|---|
定义函数 | int mkfifo(const char *pathname,mode_t mode) |
函数定义 | mkfifo()会依据参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为这个文件的权限,mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式来读取, |
返回值 | 成功返回0,失败返回-1,并将错误存于error中 |
例如
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#define FIFO "/tmp/2"
int main()
{
char buf[80] ;
int fd;
unlink(FIFO);
mkfifo(FIFO,0666);
if(fork() > 0)
{
char s[] = "hello\n";
fd = open(FIFO,O_WRONLY);
write(fd,s,sizeof(s));
close(fd);
}
else
{
fd = open(FIFO,O_RDONLY);
read(fd,buf,80);
printf("%s",buf);
close(fd);
}
return 0;
}