目录
一、管道
管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入,Linux的管道主要包括两种:无名管道和有名管道。
二、管道的类型
1、无名管道
1、只能用于具有亲缘关系的进程之间的通信
2、是一个单工的通行模式,具有固定的读端和写端
3、创建之后存在于内核中,在文件系统中不可见
读写特性:
读特性:
写端存在:
管道有数据:返回读到的字节数
管道无数据:程序阻塞
写段不存在:
管道有数据:返回读到的字节数
管道无数据:返回0
写特性:
读端存在:
管道有空间:返回写入的字节数
管道无空间:程序阻塞,直到有空间为止
读端不存在:
无论管道是否有空间,管道破裂,管道破裂进程终止
2、有名管道
1、可用于任意类型的进程之间
2、双工通信,没有固定的读端或者写端
3、创建之后可在文件系统中查看到
读写特性:
适用所有情况
三、管道的创建
1、无名管道的创建
头文件:
#include <unistd.h>
int pipe(int pipefd[2]);
参数:
pipefd:存放无名管道读端和写端的数组首地址
pipefd[0]——读端
pipefd[1]——写端返回值:
成功返回0,失败返回-1
2、有名管道的创建
头文件:
#include <sys/types.h>
#include <sys/stat.h>函数原型:
int mkfifo(const char *pathname, mode_t mode);
参数:
pathname:创建管道文件的文件名
mode:创建管道文件的权限
返回值:成功返回0,失败返回1
四、实例说明
1、无名管道实例
利用管道实现子进程输入,父进程输出
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:comunication.c
* 创 建 者:QiuCC
* 创建日期:2022年08月10日
* 描 述:利用无名管道实现子进程输入,父进程输出
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define N 100
int main(int argc, char *argv[])
{
int pipefd[2] = {0};//pipefd[0]存放管道的读端,pipefd[1]存放管道的写端
int ret;
ret = pipe(pipefd);
pid_t pid = fork();//创建子进程
if(-1 == pid){
perror("fork");
exit(-1);
}
if(ret == -1){
perror("pipe");
exit(-1);
}
if(pid == 0){//子进程
while(1){
char str[N];
fgets(str, N, stdin);//从终端获取数据
str[strlen(str) - 1] = '\0';
write(pipefd[1], str, N);//将数据写入管道
}
}else{
while(1){
char str[N];
read(pipefd[0], str, N);//将管道内容读入
puts(str);//向终端输出数据
}
wait(NULL);//等待子进程结束
}
return 0;
}
运行结果如图:子进程输入一个,父进程打印一个
2、有名管道实例
通过有名管道,实现一个程序输入,另一个程序输出
(1)、创建管道文件
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:mkfifo.c
* 创 建 者:QiuCC
* 创建日期:2022年08月10日
* 描 述:利用mkfifo()函数创建管道文件
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#define N 100
int main(int argc, char *argv[])
{
int ret = mkfifo("fifo", 0664);//创建管道文件
if(ret == -1){
perror("mkfifo");
}
return 0;
}
(2)、写文件
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:in.c
* 创 建 者:QiuCC
* 创建日期:2022年08月10日
* 描 述:创建文件实现向管道写入的功能
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define N 100
int main(int argc, char *argv[])
{
int fd = open("fifo", O_WRONLY);//以只写方式打开管道文件
if(fd == -1){
perror("open fifo");
exit(-1);
}
printf("I am in.c\n");
while(1){
char str[N] = {0};
fgets(str, N, stdin);
str[strlen(str)-1] = '\0';
write(fd, str, strlen(str));//向管道文件写入数据
}
return 0;
}
(3)、读文件
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:out.c
* 创 建 者:QiuCC
* 创建日期:2022年08月10日
* 描 述:从管道文件读取数据并输出到终端
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#define N 100
int main(int argc, char *argv[])
{
int fd = open("fifo", O_RDONLY);//以只读方式打开管道文件
if(fd == -1){
perror("open fifo");
exit(-1);
}
while(1){
char str[N] = {0};
int ret = read(fd, str, N);//从管道文件读取数据
if(ret == -1){
perror("read");
exit(-1);
}
puts(str);//输出到终端
}
return 0;
}
通过上述三个程序,我们先编译运行创建管道的文件,会发现此时有一个名为fifo的管道文件生成,显示具体信息,文件类型为管道文件。
![]()
我们接着编译in.c和out.c
我们此时打开一个另一个终端,我们先单独运行./in 。
此时我们发现,我们的终端处于等待状态,但是,我们在输入前准备输出的话“I am in.c”并没有输出。
我们接着在另一个终端运行./out,此时我们的“I am in.c”打印并输出,可见,我们的有名管道必须两端同时打开才有效。
我们接着输入数据,我们in输入一个,out就打印一个,可见我们的管道实现了两个文件之间的通信,也就是两个独立进程之间的通信。
好的,以上就是本期内容,欢迎大家参考,指正!!!