一、实验目的
1、了解有名管道通信的原理。
2、掌握有名管道的创建及使用方法。
二、实验内容
1、使用mkfifo函数创建一个有名管道。以阻塞方式打开管道,将磁盘文件test1的内容都读取到管道中。
2、以阻塞方式打开管道,将管道中的数据写入文件test2,从而在test1与test2之间完成拷贝文件的功能。
3、编译并分别在两个终端里运行读端和写端程序,查看结果。
三、实验源程序及结果截图
Fifowrite.c文件:
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include<errno.h>
#include <string.h>
int main(){
const char *fifo_name="my_fifo";
const int open_mode=O_WRONLY;
const char *open_mode_name="O_WRONLY";
if(access(fifo_name,F_OK)==-1){
int res=mkfifo(fifo_name,0777);//创建管道
if(res!=0){
printf("create failed\n");
printf("errno is:%d\n",errno);
exit(EXIT_FAILURE);
}
printf("created successful\n");
}
else{printf("next step\n");}
char buf[256];
FILE* fin;//读取文件内容
fin=fopen("test1.txt","r");
fgets(buf,255,fin);
printf("%s\n",buf);
fclose(fin);
int pipe_fd;
printf("open %s\n",fifo_name);
pipe_fd=open("my_fifo",O_WRONLY);//打开管道
printf("%d\n",pipe_fd);
if(pipe_fd!=-1){
int nwrite;
if((nwrite=write(pipe_fd,buf,sizeof(buf)))>0)//将读取出的文件内容写入到管道中
printf("Write '%s' to fifo",buf);
close(pipe_fd);
exit(0);
}
else{
printf("write failed '%d'\n",errno);
char* mesg = strerror(errno);
printf("Mesg:%s\n",mesg);
exit(EXIT_FAILURE);
}
}
Fiforead.c文件:
#include<unistd.h>
#include<stdlib.h>
#include<stdbool.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<limits.h>
#include<string.h>
int main(){
const char* fifo_name="my_fifo";
const int open_mode=O_RDONLY;
const char* open_mode_name="O_RDONLY";
char buff[256];
int fd=-1;
fd=open(fifo_name,open_mode);//打开管道
if(fd!=-1){
memset(buff,0,sizeof(buff));
read(fd,buff,255);//读取管道内容
printf("Read '%s' from fifo\n",buff);
FILE* fin;
int out;
out=open("test2.txt",O_WRONLY);//打开文件
write(out,buff,6);//将读取的管道内容写入到文件中
close(out);
exit(0);
}
else{
printf("open wrong\n");
exit(EXIT_FAILURE);
}
}
①编译两个.c文件
②运行fifowrite.c.o文件,程序运行阻塞到open my_fifo
③打开终端2,运行fiforead.c.o文件
④返回再看终端1,出现了新的内容
四、实验问题总结
个人在写这个实验的时候因为知识没掌握好,导致了很多不该出现的错误,比如在管道的创建,以及注意对管道权限的设置,在最后运行的时候要注意是以阻塞还是以非阻塞的方式打开的。调用open打开有名管道的进程可能会被阻塞。但如果同时用读写方式(O_RDWR)打开,则一定不会导致阻塞;如果以只读方式(O_RDONLY)打开,则调用open函数的进程将会被阻塞直到有写方式打开管道;同样以写方式(O_WRONLY)打开也会阻塞直到有读方式打开管道。