进程间通信方式之有名管道
2016-04-17 20:11
176 查看
在上一篇介绍了进程间通信方式之管道,链接如下:
http://blog.csdn.net/zhuyunfei/article/details/51087802
今天再来介绍下进程间通信方式之有名管道
1.有名管道
看名字就和明显了,它和匿名管道的区别就是,这个管道是有“名字”,这个名字是什么呢?就是FIFO文件路径,从文件操作我们可以大胆推理,既然有文件路径,那么这个文件就可以被不同的进程所访问,这样就实现了通过有名管道来实现不同进程间的通信,此时,有名管道就不再像匿名管道那样受限制,之前的匿名管道只能在具有亲缘关系的进程中通信,匿名管道不适用不具有亲缘关系的不同进程间通信。
有名管道也称为命名管道(named pipe),或者FIFO。
创建有名管道的函数是mkfifo,函数原型是:
int mkfifo (const char *__path, __mode_t __mode)
功能:创建新的带命名路径的FIFO
参数:path — 命名管道路径
mode — 模式权限
返回值:成功返回0,失败返回-1;
包含mkfifo定义的头文件路径是:/usr/include/x86_64-linux-gnu/sys/stat.h
2.有名管道的特点
a)使不同进程之间完成通信。
通过mkfifo创建FIFO文件建立有名管道,
使得不同进程可以通过像访问文件的方式一样来访问有名管道,
fifo文件特点:
先进先出:即写文件从有名管道数据尾端写入,数据读取从有名管道的开始处读取
b)有名管道内数据不支持如lseek()文件定位操作
3.阻塞打开与非阻塞打开
对于读进程
•若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入
•若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0
对于写进程
•若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入
•若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败
4.例子
writepipe.c
readpipe.c
编译这两个程序
如果需要加权限,
这时我们先运行readpipe进程,然后运行writepipe进程,并带一个数据参数hellonamedpipe,这时我们在readpipe进程窗口会看见它读出了writepipe进程写入到有名管道中的数据,结果如图:
http://blog.csdn.net/zhuyunfei/article/details/51087802
今天再来介绍下进程间通信方式之有名管道
1.有名管道
看名字就和明显了,它和匿名管道的区别就是,这个管道是有“名字”,这个名字是什么呢?就是FIFO文件路径,从文件操作我们可以大胆推理,既然有文件路径,那么这个文件就可以被不同的进程所访问,这样就实现了通过有名管道来实现不同进程间的通信,此时,有名管道就不再像匿名管道那样受限制,之前的匿名管道只能在具有亲缘关系的进程中通信,匿名管道不适用不具有亲缘关系的不同进程间通信。
有名管道也称为命名管道(named pipe),或者FIFO。
创建有名管道的函数是mkfifo,函数原型是:
int mkfifo (const char *__path, __mode_t __mode)
功能:创建新的带命名路径的FIFO
参数:path — 命名管道路径
mode — 模式权限
返回值:成功返回0,失败返回-1;
包含mkfifo定义的头文件路径是:/usr/include/x86_64-linux-gnu/sys/stat.h
2.有名管道的特点
a)使不同进程之间完成通信。
通过mkfifo创建FIFO文件建立有名管道,
使得不同进程可以通过像访问文件的方式一样来访问有名管道,
fifo文件特点:
先进先出:即写文件从有名管道数据尾端写入,数据读取从有名管道的开始处读取
b)有名管道内数据不支持如lseek()文件定位操作
3.阻塞打开与非阻塞打开
对于读进程
•若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入
•若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0
对于写进程
•若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入
•若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败
4.例子
writepipe.c
#include <stdio.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #define P_FIFO "/tmp/name_pipe" int main(int argc, char* argv[]) { int fd; //命令要带写入有名管道的数据 if(argc < 2){ printf("please input the write data.\n"); } //打开有名管道 //第一个参数指定有名管道路径 //第二个参数指定以写以及非阻塞方式打开有名管道 //O_WRONLY写入方式 //O_NONBLOCK阻塞模式 fd = open(P_FIFO,O_WRONLY|O_NONBLOCK); //打开有名管道失败 if(fd < 0){ printf("open failed.\n"); } //写入数据到有名管道 //第一个参数为有名管道文件描述符 //第二个参数为写入有名管道的数据 //第三个参数为写入有名管道的数据长度 write(fd,argv[1],100); //关闭有名管道 close(fd); return 0; }
readpipe.c
#include <stdio.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #define P_FIFO "/tmp/name_pipe" int main() { int ret = -1; int fd; char buffer[100]; //如果有名管道存在,则先删除它 if(access(P_FIFO,F_OK)){ execlp("rm","-f",P_FIFO,NULL); printf("access.\n"); } //创建有名管道,并赋予访问有名管道的权限 ret = mkfifo(P_FIFO,0777); //创建失败 if(ret < 0){ printf("create named pipe failed.\n"); return 0; } //打开有名管道 //第一个参数为有名管道文件路径 //第二个参数表明是以读取方式并以非阻塞方式打开有名管道 //O_RDONLY读取模式 //O_NONBLOCK非阻塞方式 fd = open(P_FIFO,O_RDONLY | O_NONBLOCK); //循环读取有名管道 while(1){ memset(buffer,0,sizeof(buffer)); if(read(fd,buffer,100) == 0){ printf("nodata.\n"); }else{ printf("getdata:%s\n",buffer); sleep(1); } } close(fd); return 0; }
编译这两个程序
sudo gcc readpipe.c -o readpipe sudo gcc writepipe.c -o writepipe
如果需要加权限,
sudo chmod 777 readpipe sudo chmod 777 writepipe
这时我们先运行readpipe进程,然后运行writepipe进程,并带一个数据参数hellonamedpipe,这时我们在readpipe进程窗口会看见它读出了writepipe进程写入到有名管道中的数据,结果如图:
相关文章推荐
- Linux进程通信(IPC)方式简介
- Web跨浏览器进程通信(Web跨域)
- Linux C 编程----有名管道FIFO
- android的AIDL----讲述进程间通信
- android的Bound Service----讲述进程间通信
- 生产者消费者问题分析
- Linux进程通信
- aidl的使用简介
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
- Linux的SOCKET编程详解
- android进程间的通信方式AIDL
- Linux应用程序开发笔记->六种进程间通信方式
- Linux进程通信之消息队列
- 共享内存的删除
- 进程通信
- Windows管道通信实现进程通信
- 在操作系统中,进程之间是如何通信的?
- Android之进程通信机制(上)(Serializable,Parcelable,Binder)
- UNIX进程间的通信 FIFO
- Linux进程间通信——消息队列