Linux下实现进程通信的方式有很多种,今天要说的是有名管道,有名管道比命名管道的优势是可以在任何进程之间传递数据。有名管道通信是依赖于管道文件这种特殊类型文件来进行的。
目录
1.mkfifo命令
2.mkfifo库函数
1.mkfifo命令
mkfifo命令可以创建管道文件,例如:
如上文件类型是p代表的就是管道文件。
2.mkfifo库函数
man 3 mkfifo
mkfifo函数是glibc库中实现的一个接口,如下利用mkfifo来实现进程之间数据传输。
server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <assert.h>
#include <fcntl.h>
#define FIFO_PATH "./fifo"
int main()
{
umask(0);
// 创建管道
int ret = mkfifo(FIFO_PATH, 0666);
// 打开管道
int fd = open(FIFO_PATH, O_RDONLY);
if(fd > 0) {
char buf[1024] = {0};
while(1){
//管道读取数据
int ret = read(fd, buf, sizeof(buf) - 1);
buf[ret] = 0;
if(ret > 0){
printf("%s", buf);
fflush(stdout);
}
// 客户端不写入数据,则停止读取
else if(ret == 0){
printf("client quit\n");
break;
}
else{
perror("read filed\n");
break;
}
}
}
close(fd);
return 0;
}
client.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
#define FIFO_PATH "./fifo"
#define WRITE_TIMES 5
/*
标准输入输出错误输出 FILE*:
stdin
stdout
stderr
标准输入输出错误输出fd:
STDIN_FILENO 0
STDOUT_FILENO 1
STDERR_FILENO 2
*/
int main()
{
//打开管道
int fd = open(FIFO_PATH, O_WRONLY);
char buf[64] = {0};
int times = 0;
while(1)
{
// 写入5次
if (++times > WRITE_TIMES) {
break;
}
printf("please input info :");
fflush(stdout);
//从标准输入获取数据写入进管道。
ssize_t ret = read(0, buf, sizeof(buf) - 1);
if(ret > 0){ //将读取到的数据往文件中写入
buf[ret] = 0;
write(fd, buf, sizeof(buf) - 1);
}
else {
perror("read");
}
}
close(fd);
return 0;
}
Makefile
.PHONY: all
all: server client
server: server.c
gcc -o $@ $^
client: client.c
gcc -o $@ $^
.PHONY: clean
clean:
rm server client fifo -rf
代码结构:
运行两个server进程,两个client进程
从运行结果看, 两个client进程往管道写入5段数据信息,两个server进程从管道读取数据,管道有互斥功能,同一时刻只能有一个进程从管道读取数据。