一、任务
1、学习mkfifo等函数;
2、了解有名管道的特点、阻塞打开与非阻塞打开等;
3、编写一个关于有名管道进程通信的程序,并运行。
二、相关概念
1、相关函数
创建有名管道的函数是mkfifo,函数原型是:
int mkfifo (const char *__path, __mode_t __mode)
功能:创建新的带命名路径的FIFO
参数:path — 命名管道路径
mode — 模式权限
返回值:成功返回0,失败返回-1;
2、有名管道的特点
a)、使不同进程之间完成通信。
通过mkfifo创建FIFO文件建立有名管道,
使得不同进程可以通过像访问文件的方式一样来访问有名管道,
fifo文件特点:先进先出:即写文件从有名管道数据尾端写入,数据读取从有名管道的开始处读取。
b)、有名管道内数据不支持如lseek()文件定位操作。
3、阻塞打开与非阻塞打开
对于读进程:
•若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入;
•若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0、
对于写进程:
•若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入;
•若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。
三、实验代码及运行结果
1、代码
分别输入形成三个文件 mkfifo.c、client.c、service.c,代码如下:
/*mkfifo.c*/ #include"stdio.h" #include"unistd.h" int main() { int ret; ret=mkfifo("./a.c",0777); if(ret<0) { printf("creat fifo a.c failure "); return -1; } printf("creat mkfifo.c sucess "); return 0; }
/*service.c*/ #include"unistd.h" #include"fcntl.h" #include"stdio.h" #include"stdlib.h" #include"string.h" int main() { int fd; char rdbuf[128]={0}; fd=open("./a.c",O_RDONLY); if(fd<0) { printf("open fifo a.c failure "); return -1; } while(1) { read(fd,rdbuf,128); printf("recv from fifo data:%s",rdbuf); if(!strcmp(rdbuf,"quit ")) break; memset(rdbuf,0,128); } sleep(1); close(fd); return 0; }
/*client.c*/ #include"unistd.h" #include"fcntl.h" #include"stdio.h" #include"stdlib.h" #include"string.h" int main() { int fd; char wrbuf[128]; fd=open("./a.c",O_WRONLY); if(fd<0) { printf("open fifo a.c failure "); return -1; } while(1) { memset(wrbuf,0,sizeof(wrbuf)); fgets(wrbuf,128,stdin); write(fd,wrbuf,strlen(wrbuf)); if(!strcmp(wrbuf,"quit ")) { break; } } sleep(1); close(fd); return 0; }
2、编译运行
1)、生成可执行文件
终端输入:
gcc mkfifo.c -o mkfifo
gcc service.c -o service
gcc client.c -o client
2)、运行
先运行mkfifo,终端输入: ./mkfifo
打开两个终端分别运行 service、client
终端分别输入 : ./service ./client
即可实现通信!