1、匿名管道通信
源程序:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int wc=1,rc=1;
char wstr[100]; // 在此处声明了全局变量wstr
void writer (const char* message, int count, FILE* stream)
{
for (; count > 0; --count) {
fprintf (stream, "%s:%d\n", message,wc);
sprintf(wstr,"%s:%d\n", message,wc);
fflush (stream);
printf("第%d次写入管道的内容为:%s",wc,wstr);
wc++;
sleep (1);
}
}
void reader (FILE* stream)
{
char buffer[1024];
while (!feof (stream) && !ferror (stream) && fgets (buffer, sizeof (buffer), stream) != NULL)
{
printf("读进程第%d次读取:",rc);
rc++;
fputs (buffer, stdout);
}
}
int main ()
{
int fds[2];
pid_t pid;
pipe (fds);
pid = fork ();
if (pid == (pid_t) 0) {
FILE* stream;
close (fds[1]);
stream = fdopen (fds[0], "r");
reader (stream);
close (fds[0]);
}
else {
FILE* stream;
close (fds[0]);
stream = fdopen (fds[1], "w");
writer ("Hello, world.", 5, stream);
close (fds[1]);
}
return 0;
}
编译链接命令:gcc pipec.c -o pipec
运行命令:./pipec
交互与结果:
2、有名管道通信
源程序:
fifo_write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define FIFO "myfifo" // 有名管道名字
#define BUFF_SIZE 1024
int main(int argc, char *argv[]) {
char buff[BUFF_SIZE]; // 欲写入管道的数据缓冲区
ssize_t real_write; // 写入管道的字节数,使用ssize_t代替int
int fd; // 管道描述符
int rw = 1; // 管道写次数
if (access(FIFO, F_OK) == -1) {
// 测试有名管道FIFO是否存在,若不存在,则用mkfifo创建该管道
if ((mkfifo(FIFO, 0666) < 0) && (errno != EEXIST)) {
// 创建管道"myfifo",允许读写
perror("Can NOT create fifo file"); // 使用perror输出错误信息
exit(1);
}
}
if ((fd = open(FIFO, O_WRONLY)) == -1) {
// 调用open以只写方式打开FIFO,返回文件描述符fd
perror("Open fifo error"); // 使用perror输出错误信息
exit(1);
}
do {
printf("请输入要写入管道的内容(输入q退出):");
// 使用fgets代替gets,因为gets不安全,会造成缓冲区溢出
if (fgets(buff, BUFF_SIZE, stdin) != NULL) {
// 去除可能包含的换行符
buff[strcspn(buff, "\n")] = 0;
// 只写入用户输入的有效字符串长度,而不是整个缓冲区
if ((real_write = write(fd, buff, strlen(buff))) > 0) {
printf("第%d次写入管道: '%s'.\n", rw++, buff);
} else {
perror("Write to fifo error"); // 如果写入失败,打印错误信息
break;
}
// 如果用户输入了q,则退出循环
if (strcmp(buff, "q\n") == 0 || strcmp(buff, "q") == 0) {
break;
}
}
} while (strlen(buff) != 0);
close(fd);
exit(0);
}
fifo_read.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define FIFO "myfifo"
#define BUFF_SIZE 1024
int main() {
char buff[BUFF_SIZE];
ssize_t real_read; // 使用 ssize_t 而不是 int
int fd;
int rc = 1;
if (access(FIFO, F_OK) == -1) {
if ((mkfifo(FIFO, 0666) < 0) && (errno != EEXIST)) {
perror("Can NOT create fifo file");
exit(1);
}
}
if ((fd = open(FIFO, O_RDONLY)) == -1) {
perror("Open fifo error");
exit(1);
}
while (1) {
memset(buff, 0, BUFF_SIZE);
if ((real_read = read(fd, buff, BUFF_SIZE - 1)) > 0) { // 减1留给字符串结束符
buff[real_read] = '\0'; // 添加字符串结束符
printf("第%d次读取管道: '%s'.\n", rc++, buff);
} else if (real_read == 0) {
// 读取到EOF,这通常不会在有名管道中发生,但可以用于普通文件
break;
} else if (errno == EINTR) {
// 如果读取被中断(例如,由于信号),则重试
continue;
} else {
// 发生错误
perror("Read from fifo error");
break;
}
}
close(fd);
exit(0);
}
编译链接命令:gcc fifo_write.c -o fifo_write
gcc fifo_read.c -o fifo_read
运行命令:./fifo_write
./fifo_read
注意:需要两个终端分别运行
交互与结果: