操作系统第三次实验报告——有名管道(FIFO)
0 个人信息
- 张樱姿
- 201821121038
- 计算1812
1 实验目的
- 掌握进程间通信管道的编程。
2 实验内容
- 在服务器上用vim编写一个程序:创建一个命名管道,创建两个进程分别对管道进行读(
read_fifo.c)
和写(write_fifo.c)
。给出源代码 - 给出运行结果,并分析
3 实验报告
3.1 编写写管道程序(write_fifo.c)
1 #include<unistd.h> //write,read,close,access 2 #include<string.h> //memset 3 #include<errno.h> //errno 4 #include<fcntl.h> //open,o_wronly,o_rdonly 5 #include<stdio.h> //printf,sscanf 6 #include<stdlib.h> //exit 7 #include<limits.h> //pipe_buf 8 9 #define myfifo "/tmp/myfifo" //有名管道文件名 10 #define bufes pipe_buf 11 12 int main(int argc,char * argv[]) 13 { 14 int fd,n; 15 char buff[bufes]; 16 17 if(argc <= 1) 18 { 19 exit(1); 20 } 21 sscanf(argv[1],"%s",buff); 22 //以只写阻塞方式打开fifo管道 23 fd = open(myfifo,o_wronly); 24 if(fd==-1) 25 { 26 printf("open fifo error\n"); 27 exit(1); 28 } 29 //向管道中写入字符串 30 if((n = write(fd,buff,bufes))>0) 31 { 32 printf("finish writing '%s' to fifo\n",buff); 33 } 34 close(fd); 35 exit(0); 36 }
3.2 编写读管道程序(read_fifo.c)
1 #include<unistd.h> //write,read,close,access 2 #include<string.h> //memset 3 #include<errno.h> //errno 4 #include<fcntl.h> //open,o_wronly,o_rdonly 5 #include<stdio.h> //printf,sscanf 6 #include<stdlib.h> //exit 7 #include<limits.h> //pipe_buf 8 9 #define myfifo "/tmp/myfifo" 10 #define bufes pipe_buf 11 12 int main() 13 { 14 int fd,n; 15 char buff[bufes]; 16 //判断有名管道是否已存在 17 if(access(myfifo,f_ok)==-1) 18 { //若不存在,则创建可读可写的有名管道 19 if((mkfifo(myfifo,0666)<0)&&(errno != eexist)) 20 { 21 printf("could't create fifo\n"); 22 exit(1); 23 } 24 } 25 //以只读阻塞方式打开有名管道 26 fd = open(myfifo,o_rdonly); 27 if(fd==-1) 28 { 29 printf("open fifo error\n"); 30 exit(1); 31 } 32 //不停读取管道中的数据,如果没用数据可读,则一直处于阻塞状态 33 while(1) 34 { 35 memset(buff,0,sizeof(buff)); 36 if((n = read(fd,buff,bufes))>0) 37 { 38 printf("read '%s' from fifo\n",buff); 39 } 40 } 41 close(fd); 42 exit(0); 43 }
3.3 运行结果及分析
为了能够较好地观察运行结果,将两程序分别编译后,把这两个程序分别在两个终端里运行,在这里首先启动读管道程序。读管道进程在建立管道后就开始循环地从管道里读出内容,如果没有数据可读,则一直阻塞到写管道进程向管道写入数据。在启动了写管道程序后,读进程能够从管道里读出用户的输入内容,程序运行结果如下:
分析:
①对于读进程:
· 若该管道是阻塞打开,且当前fifo内无数据,则对读进程而言一直阻塞到有数据写入。
· 若该管道是非阻塞打开,则不论fifo内是否有数据,都进程都会立即执行读操作。也就是说若fifo内无数据,那么读程序将立马返回0。
此处使用的是阻塞方式。
②对于写进程:
· 若该管道是阻塞打开,则写进程将一直阻塞到有数据写入。
· 若该管道是非阻塞打开而不能写入全部数据,则对读进程而言只能进行部分写入或者调用失败。
③管道模式:
· o_rdonly:读管道。
· o_wronly:写管道。
· o_rdwr:读写管道。
· o_nonblock:非阻塞。
· o_creat:如果该文件不存在,就创建一个新的文件,并使用第3个参数为其设置权限。
· o_excl:测试文件是否存在。如果使用o_creat|o_creat时文件存在,那么将返回出错:errno == eexist。
3.4 创建两个有名管道实现聊天程序
服务器端程序:
1 /*server.c*/ 2 #include<unistd.h> 3 #include<string.h> 4 #include<errno.h> 5 #include<fcntl.h> 6 #include<stdio.h> 7 #include<stdlib.h> 8 #include<limits.h> 9 10 #define write_fifo "/tmp/readfifo" 11 #define read_fifo "/tmp/writefifo" 12 #define bufes pipe_buf 13 14 int main(int argc,char * argv[]) 15 { 16 int wfd,rfd,n; 17 char buff[bufes],readbuff[bufes]; 18 //创建管道write_fifo 19 mkfifo(write_fifo, s_ififo|0666); 20 //以只读阻塞方式打开fifo管道 21 rfd = open(read_fifo,o_rdonly); 22 //以只写阻塞方式打开fifo管道 23 wfd = open(write_fifo,o_wronly); 24 //不停读取管道中的数据,如果没用数据可读,则一直处于阻塞状态 25 while(1){ 26 memset(readbuff,0,sizeof(readbuff)); 27 if((n = read(rfd,readbuff,bufes))>0) 28 { 29 readbuff[bufes] = '\0'; 30 printf("client: %s\n",readbuff); 31 } 32 memset(buff,0,sizeof(buff)); 33 printf("server: "); 34 fgets(buff, bufes, stdin); 35 buff[strlen(buff)-1] = '\0'; 36 37 write(wfd,buff,strlen(buff)); 38 } 39 close(wfd); 40 close(rfd); 41 exit(0); 42 }
客户端程序:
1 /*client.c*/ 2 #include<unistd.h> 3 #include<string.h> 4 #include<errno.h> 5 #include<fcntl.h> 6 #include<stdio.h> 7 #include<stdlib.h> 8 #include<limits.h> 9 10 #define write_fifo "/tmp/writefifo" 11 #define read_fifo "/tmp/readfifo" 12 #define bufes pipe_buf 13 14 int main(int argc,char * argv[]) 15 { 16 int wfd,rfd,n; 17 char buff[bufes],readbuff[bufes]; 18 //创建管道read_fifo 19 mkfifo(write_fifo, s_ififo|0666); 20 //以只写阻塞方式打开fifo管道 21 wfd = open(write_fifo,o_wronly); 22 //以只读阻塞方式打开fifo管道 23 rfd = open(read_fifo,o_rdonly); 24 //不停读取管道中的数据,如果没用数据可读,则一直处于阻塞状态 25 while(1) 26 { 27 memset(buff,0,sizeof(buff)); 28 printf("client: "); 29 fgets(buff, bufes, stdin); 30 buff[strlen(buff)-1] = '\0'; 31 32 write(wfd,buff,strlen(buff)); 33 memset(readbuff,0,sizeof(readbuff)); 34 if((n = read(rfd,readbuff,bufes))>0) 35 { 36 printf("server: %s\n",readbuff); 37 } 38 } 39 close(wfd); 40 close(rfd); 41 exit(0); 42 }
3.5 运行效果及分析
分析:在这里首先启动客户端程序,再启动服务器端程序。客户端在建立管道后,首先写入数据到管道中,接着数据传递到服务器端,然后服务器端将数据写入管道中,再传递到客户端,如此往复循环。如果没有数据可读,则一直阻塞到写管道进程向管道写入数据。
4 references
上一篇: Warshall关系传递闭包