5. 管道与FIFO
管道
概述
创建和使用管道
#include <unistd.h>
// 创建管道,返回两个打开的文件描述符 filedes[0] filedes[1],分别为读取端和写入端
// 成功返回 0,失败返回 -1
// 因为是文件描述符,可以使用 read write 调用在管道上执行 IO
int pipe(int filedes[2]);FIFO



最后更新于
#include <unistd.h>
// 创建管道,返回两个打开的文件描述符 filedes[0] filedes[1],分别为读取端和写入端
// 成功返回 0,失败返回 -1
// 因为是文件描述符,可以使用 read write 调用在管道上执行 IO
int pipe(int filedes[2]);


最后更新于
#include <sys/stat.h>
// 创建一个命名管道,此命令还是一个 Linux 命令:
// mkfifo [ -m mode ] pathname
// 在不使用此 FIFO 后调用 unlink 删除此文件
// 成功返回 0,失败返回
int mkfifo(const char *pathname, mode_t mode);S_IRUSR:用户读权限
S_IWUSR:用户写权限
S_IXUSR:用户执行权限
S_IRGRP:组读权限
S_IWGRP:组写权限
S_IXGRP:组执行权限
S_IROTH:其他用户读权限
S_IWOTH:其他用户写权限
S_IXOTH:其他用户执行权限// fifo_info.h 包装了读写函数和消息结构
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
// 服务端 接收客户端信息
#define FIFO_SERVER "./fifo_server.fifo"
// 客户端 给服务端发送信息,这里只有一个客户端所以写死了,多个客户端可以设计一种命名约定(用 PID 标识)
#define FIFO_CLIENT "./fifo_client.fifo"
#define BUF_SIZE (PIPE_BUF - sizeof(int))
typedef struct {
int length;
char buf[BUF_SIZE];
} Message;
// 从 fd 中读取数据存入 msg
int read_fifo(int fd, Message *msg) {
if(read(fd, &(msg->length), sizeof(msg->length)) == -1) {
perror("Read Message Length Error!");
return -1;
}
if(read(fd, msg->buf, msg->length) == -1) {
perror("Read Message Buf Error!");
return -1;
}
return 0;
}
// 向 fd 写入消息
int write_fifo(int fd, const Message *msg) {
if(write(fd, &msg->length, sizeof(msg->length)) == -1) {
perror("Write Message Length Error!");
return -1;
}
if(write(fd, msg->buf, msg->length) == -1) {
perror("Write Message Buf Error!");
return -1;
}
return 0;
}// fifo_server.c FIFO 服务器,将客户端的字符串转为大写
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include "fifo_info.h"
int main() {
if(mkfifo(FIFO_SERVER, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
perror("Make FIFO_SERVER Error.");
return -1;
}
int fd = open(FIFO_SERVER, O_RDONLY);
// 使其阻塞,否则后面的 read 会返回 EOF
int fd2 = open(FIFO_SERVER, O_WRONLY);
Message msg;
setbuf(stdout, NULL);
while(1) {
// 读取数据
if(read_fifo(fd, &msg) != 0) {
return -1;
}
// 改为大写
for(int i = 0;i < msg.length;++i) {
msg.buf[i] = toupper(msg.buf[i]);
}
// 打开客户端 FIFO 发送数据
int fd_c = open(FIFO_CLIENT, O_WRONLY);
if(fd_c < 0) {
perror("Open Client FIFO Error.");
return -1;
}
if(write_fifo(fd_c, &msg) != 0) {
return -1;
}
close(fd_c);
}
return 0;
}// fifo_client 客户端 将命令行数据发送给服务器
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include "fifo_info.h"
int main(int argc, char *argv[]) {
if(mkfifo(FIFO_CLIENT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
perror("Make FIFO_CLIENT Error.");
return -1;
}
setbuf(stdout, NULL);
int fd_server = open(FIFO_SERVER, O_WRONLY);
Message msg;
for(int i = 1;i < argc;++i) {
msg.length = strlen(argv[i]);
memcpy(msg.buf, argv[i], msg.length);
// 发送数据
if(write_fifo(fd_server, &msg) != 0) {
return -1;
}
int fd_client = open(FIFO_CLIENT, O_RDONLY);
if(read_fifo(fd_client, &msg) != 0) {
return -1;
}
close(fd_client);
write(STDOUT_FILENO, msg.buf, msg.length);
printf("\n");
}
close(fd_server);
return 0;
}❯ ./fifo_server&
[1] 5555
❯ ./fifo_client hello world linux
HELLO
WORLD
linux