1,有名管道的特点
- 对应管道文件,可用于任意进程之间进行通信:有名管道创建好之后,在系统中有实际的文件和有名管道对应,任意两个进程可以通过路径和文件名指定同一个有名管道进行通信
- 打开管道时可指定读写方式:有名管道用open()打开的时候可以指定不同的读写方式,从而可以确定读端和写端
- 通过文件IO操作,内容存放在内存中:通过文件IO read()和write()进行操作。虽然有名管道有一个实际的文件被创建,在文件系统中可见,但是往管道中写入的所有内容实际上依然是存放在内存中的(跟无名管道一样),当所有的读端和写端都关闭的时候,管道存放在内存中的内容都会被释放
- 有名管道打开的时候有可能会阻塞。当只有读端或只有写端的时候,open()会阻塞,只有当读端和写端同时存在的时候,open()才会返回,程序才会继续执行。
2,有名管道的创建mkfifo()
#include <unistd.h>
#include <fcntl.h>
int mkfifo(const char *path, mode_t mode);
- 成功时返回0,失败时返回EOF(如果创建的管道已经存在,创建就会失败)
- path 创建的管道文件路径
- mode 管道文件的权限,如0666(管道文件的权限主要是读写权限)
3,有名管道读写—示例
进程A:循环从键盘输入并写入有名管道myfifo,输入quit时退出
进程B:循环统计进程A每次写入myfifo的字符串的长度
/* create_fifo.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
if(mkfifo("myfifo",0666) < 0)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
/* write_fifo.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
char buf[N];
int pfd;
if((pfd = open("myfifo",O_WRONLY)) < 0)
{
perror("open");
exit(-1);
}
printf("write myfifo\n");//进程打开管道后显示这一句
while(1)
{
printf("Please input a string (quite exit!\n");
fgets(buf,N,stdin);
if(strcmp(buf,"quite\n") == 0)break;
write(pfd,buf,N);
}
close(pfd);
return 0;
}
/* read_fifo.c */
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
char buf[N];
int pfd;
if((pfd = open("myfifo",O_RDONLY)) < 0)
{
perror("open");
exit(-1);
}
printf("read myfifo\n");//进程打开管道后显示这一句
while(read(pfd,buf,N) > 0)//写端存在,管道中没有数据的时候,读管道阻塞;写端不存在,管道中没有数据的时候,read()返回0
{
printf("the length of string is %d\n",strlen(buf));
}
close(pfd);
return 0;
}
1,创建好三个c文件,并编译
linux@linux:~/test/stdio/fifo_sample$ ls
fifo_create.c fifo_read.c fifo_write.c
linux@linux:~/test/stdio/fifo_sample$ gcc fifo_create.c -o fifo_create.out
linux@linux:~/test/stdio/fifo_sample$ gcc fifo_write.c -o fifo_write.out
linux@linux:~/test/stdio/fifo_sample$ gcc fifo_read.c -o fifo_read.out
linux@linux:~/test/stdio/fifo_sample$ ls
fifo_create.c fifo_create.out fifo_read.c fifo_read.out fifo_write.c fifo_write.out
2,运行fifo_create.out,可以看到多了管道文件
linux@linux:~/test/stdio/fifo_sample$ ./fifo_create.out
linux@linux:~/test/stdio/fifo_sample$ ll
total 44
drwxrwxr-x 2 linux linux 4096 11月 12 11:13 ./
drwxrwxr-x 6 linux linux 4096 11月 12 01:01 ../
-rw-rw-r-- 1 linux linux 185 11月 12 10:13 fifo_create.c
-rwxrwxr-x 1 linux linux 7418 11月 12 11:04 fifo_create.out*
-rw-rw-r-- 1 linux linux 379 11月 12 11:03 fifo_read.c
-rwxrwxr-x 1 linux linux 7647 11月 12 11:05 fifo_read.out*
-rw-rw-r-- 1 linux linux 438 11月 12 11:03 fifo_write.c
-rwxrwxr-x 1 linux linux 7681 11月 12 11:04 fifo_write.out*
prw-rw-r-- 1 linux linux 0 11月 12 11:13 myfifo|
- 可以看到管道文件大小是0,实际上管道文件大小永远是0,因为管道中的内容是保存在内存里的,而不是磁盘上
3,运行fifo_read.out或fifo_write.out,可以看到程序处于阻塞状态。以先运行fifo_read.out为例(先运行写管道也一样)
linux@linux:~/test/stdio/fifo_sample$ ./fifo_read.out
linux@linux:~/test/stdio/fifo_sample$ ps -aux |grep fifo
linux 3089 0.0 0.5 15196 6072 pts/10 S+ 10:49 0:01 vi fifo_read.c
linux 3306 0.0 0.0 2024 280 pts/12 S+ 11:15 0:00 ./fifo_read.out
linux 3314 0.0 0.0 6108 852 pts/0 S+ 11:18 0:00 grep --color=auto fifo
- 当进程打开一个有名管道的时候,如果当前只有读端或只有写端,open()会阻塞
open()的下一条指令
printf(“read myfifo\n”);//进程打开管道后显示这一句
没有执行 - 只有当读端和写端都存在是,两个进程中的open()才能正常执行
4,在另一个终端运行
读进程 | 写进程 |
---|---|
linux@linux:~/test/stdio/fifo_sample$ ./fifo_read.out |
|
write myfifo |
linux@linux:~/test/stdio/fifo_sample$ ./fifo_write.out write myfifo Please input a string (quite exit! |
the length of string is 4 |
qwe Please input a string (quite exit! |
the length of string is 2 |
w Please input a string (quite exit! |
linux@linux:~/test/stdio/fifo_sample$ |
quite linux@linux:~/test/stdio/fifo_sample$ |
- 运行fifo_write.out后,管道有了写端,读进程和写进程的open()才能正常运行,可以看到open()的下一条指令
printf(“read myfifo\n”);//进程打开管道后显示这一句
printf(“write myfifo\n”);//进程打开管道后显示这一句
正常执行了 - 当写端输入quite时,写端不存在了,当写端不存在了,并且管道中没有数据数据,读管道会立刻返回0,返回0,就会退出循环,程序结束