操作系统第三次实验报告——有名管道(FIFO)
Linux下有名管道mkfifo单向读写实例及双向通信应用
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,access2 #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
12int main(int argc,char * argv[])
13{
14int fd,n;
15char buff[BUFES];
16
17if(argc <= 1)
18 {
19 exit(1);
20 }
21 sscanf(argv[1],"%s",buff);
22//以只写阻塞方式打开FIFO管道
23 fd = open(MYFIFO,O_WRONLY);
24if(fd==-1)
25 {
26 printf("Open fifo error
");
27 exit(1);
28 }
29//向管道中写入字符串
30if((n = write(fd,buff,BUFES))>0)
31 {
32 printf("Finish writing "%s" to FIFO
",buff);
33 }
34 close(fd);
35 exit(0);
36 }
3.2 编写读管道程序(read_fifo.c)
1 #include<unistd.h> //write,read,close,access2 #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
12int main()
13{
14int fd,n;
15char buff[BUFES];
16//判断有名管道是否已存在
17if(access(MYFIFO,F_OK)==-1)
18 { //若不存在,则创建可读可写的有名管道
19if((mkfifo(MYFIFO,0666)<0)&&(errno != EEXIST))
20 {
21 printf("Could"t create fifo
");
22 exit(1);
23 }
24 }
25//以只读阻塞方式打开有名管道
26 fd = open(MYFIFO,O_RDONLY);
27if(fd==-1)
28 {
29 printf("Open fifo error
");
30 exit(1);
31 }
32//不停读取管道中的数据,如果没用数据可读,则一直处于阻塞状态
33while(1)
34 {
35 memset(buff,0,sizeof(buff));
36if((n = read(fd,buff,BUFES))>0)
37 {
38 printf("Read "%s" from FIFO
",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
14int main(int argc,char * argv[])
15{
16int wfd,rfd,n;
17char 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//不停读取管道中的数据,如果没用数据可读,则一直处于阻塞状态
25while(1){
26 memset(readbuff,0,sizeof(readbuff));
27if((n = read(rfd,readbuff,BUFES))>0)
28 {
29 readbuff[BUFES] = "";
30 printf("Client: %s
",readbuff);
31 }
32 memset(buff,0,sizeof(buff));
33 printf("Server: ");
34 fgets(buff, BUFES, stdin);
35 buff[strlen(buff)-1] = "";
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
14int main(int argc,char * argv[])
15{
16int wfd,rfd,n;
17char 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//不停读取管道中的数据,如果没用数据可读,则一直处于阻塞状态
25while(1)
26 {
27 memset(buff,0,sizeof(buff));
28 printf("Client: ");
29 fgets(buff, BUFES, stdin);
30 buff[strlen(buff)-1] = "";
31
32 write(wfd,buff,strlen(buff));
33 memset(readbuff,0,sizeof(readbuff));
34if((n = read(rfd,readbuff,BUFES))>0)
35 {
36 printf("Server: %s
",readbuff);
37 }
38 }
39 close(wfd);
40 close(rfd);
41 exit(0);
42 }
3.5 运行效果及分析
分析:在这里首先启动客户端程序,再启动服务器端程序。客户端在建立管道后,首先写入数据到管道中,接着数据传递到服务器端,然后服务器端将数据写入管道中,再传递到客户端,如此往复循环。如果没有数据可读,则一直阻塞到写管道进程向管道写入数据。
4 References
- https://blog.csdn.net/ccskyer/article/details/24989961
- https://blog.csdn.net/MONKEY_D_MENG/article/details/5570468
- https://blog.csdn.net/CSDN_LQR/article/details/52170717
以上是 操作系统第三次实验报告——有名管道(FIFO) 的全部内容, 来源链接: utcz.com/z/515512.html