Linux学习笔记25——命名管道(FIFO)
1 命名管道(FIFO)
管道应用的一个重大缺陷就是没有名字,因此只能用于亲缘进程之间的通信。后来从管道为基础提出命名管道(named pipe,FIFO)的概念,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。
2 命名管道的创建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, //文件的路径
mode_t mode //和open函数mode一样
);
如果pathname路径下的文件已经存在,则mkfifo返回-1,errono将会返回EEXIST。
3 命名管道操作
FIFO在文件系统中表现为一个文件,大部分的系统文件调用都可以在FIFO上面,比如:read,open,write,close,unlink,stat等函数,但是seek函数不能对FIFO调用。
可以调用open打开FIFO,请注意以下方面:
A 当以阻塞(未指定O_NONBLOCK)方式只读打开FIFO的时候,则将会被阻塞,直到有其他进程以写方式打开该FIFO。
B 类似的,当以阻塞(未指定O_NONBLOCK)方式只写打开FIFO的时候,则将会被阻塞,直到有其他进程以读方式打开该FIFO
C 当以非阻塞方式(指定O_NONBLOCK)方式只读打开FIFO的时候,则立即返回。当只写open时,如果没有进程为读打开FIFO,则返回-1,其errno是ENXIO
4 应用实例
本例为一个client-server模式,服务器端将会创建一个闻名fifo文件(本例中为“/tmp/server”),并读取该fifo文件。客户端则打开该fifo文件,并把其请求写入该FIFO文件。服务器端读取该命令并执行之。
服务器端的代码为:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h> #define SERVER_FIFO_NAME "/tmp/serv_fifo"
#define CLIENT_FIFO_NAME "/tmp/cli_%d_fifo"
#define BUFFER_SIZE 20 struct data_to_pass_st{
pid_t client_pid;
char some_data[BUFFER_SIZE-];
}; int main(){
int server_fifo_fd,client_fifo_fd;
struct data_to_pass_st mydata;
int read_res;
char client_fifo[];
char *tmp_char_ptr; mkfifo(SERVER_FIFO_NAME,);
server_fifo_fd=open(SERVER_FIFO_NAME,O_RDONLY);
if(server_fifo_fd==-){
fprintf(stderr,"Server fifo failure\n");
exit(EXIT_FAILURE);
}
sleep();
do{
read_res=read(server_fifo_fd,&mydata,sizeof(mydata));
if(read_res>){
tmp_char_ptr=my_data.some_data;
while(*tmp_char_ptr>){
//把some_data中的所有字符全部转换为大写
*tmp_char_ptr=toupper(*tmp_char_ptr);
tmp_char_ptr++;
}
sprintf(client_fifo,CLIENT_FIFO_NAME,my_data.client_pid);
client_fifo_fd=open(client_fifo,O_WRONLY);
if(client_fifo_fd!=-){
write(client_fifo_fd,&my_data,sizeof(my_data));
close(client_fifo_fd);
} }
}while(read_res>);
close(server_fifo_fd);
unlink(SERVER_FIFO_NAME);
exit(EXIT_SUCCESS);
}
客户端代码为:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h> #define SERVER_FIFO_NAME "/tmp/serv_fifo"
#define CLIENT_FIFO_NAME "/tmp/cli_%d_fifo"
#define BUFFER_SIZE 20 struct data_to_pass_st{
pid_t client_pid;
char some_data[BUFFER_SIZE-];
}; int main(){
int server_fifo_fd,client_fifo_fd;
struct data_to_pass_st my_data;
int times_to_send;
char client_fifo[]; server_fifo_fd=open(SERVER_FIFO_NAME,O_WRONLY);
if(server_fifo_fd==-){
fprintf(stderr,"Sorry,no server\n");
exit(EXIT_FAILURE);
}
my_data.client_pid=getpid();
sprintf(client_fifo,CLIENT_FIFO_NAME,my_data.client_pid);
if(mkfifo(client_fifo,)==-){
fprintf(stderr,"Sorry,can't make %s\n",client_fifo);
exit(EXIT_FAILURE);
}
for(times_to_send=;times_to_send<;times_to_send++){
sprintf(my_data.some_data,"Hello from %d",my_data.client_pid,my_data.some_data);
write(server_fifo_fd,&my_data,sizeof(my_data));
client_fifo_fd=open(client_fifo,O_RDONLY);
if(client_fifo_fd!=-){
if(read(client_fifo_fd,&my_data,sizeof(my_data))>){
printf("received:%s\n",my_data.some_data);
}
close(client_fifo_fd);
}
}
close(server_fifo_fd);
unlink(client_fifo);
exit(EXIT_SUCCESS); }
5 总结
与管道相比,FIFO最大的特点就是其在文件系统中有fifo文件存在,这样就可以做到进程间通信。
6 FIFO的缺点
当然FIFO也有它的局限性。客户端可以发请求到服务器,但前提是要知道一个公共的FIFO通道,对于实现服务器回传应答到客户端的问题,可以通过为每一个客户端创建一个专用的FIFO,来实现回传应答。但也有不足,服务器会同时应答成千上万个客户端,创建如此多的FIFO是否会使系统负载过大,相应的如何判断客户端是否因意外而崩溃成为难题,或者客户端不读取应答直接退出,所以服务器必须处理SIGPIPE信号,并做相应处理。(当没有进程为读打开FIFO文件时,write函数进行写操作会产生SIGPIPE信号)
Linux学习笔记25——命名管道(FIFO)的更多相关文章
- Linux学习笔记24——进程管道
一 管道的作用 通常把一个进程的输出通过管道连接到另一个进程的输入. 二 popen和pclose函数 #include <stdio.h> FILE *popen(const char ...
- Linux学习笔记——管道PIPE
管道:当从一个进程连接数据流到另一个进程时,使用术语管道(pipe).# include <unistd.h> int pipe(int filedes[2]); //创建管道 pipe( ...
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...
- Linux 学习笔记
Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...
- 91 Testing Linux学习笔记
91 Testing Linux学习笔记... 学习地址:91Testing 的Linux教程=====================学习网址:http://www.91testing.net/ar ...
- (转)Linux最常用指令及快捷键 Linux学习笔记
Linux最常用指令及快捷键 Linux学习笔记 原文:http://blog.csdn.net/yanghongche/article/details/50827478 [摘自 鸟叔的私房菜]--转 ...
- Linux学习笔记(六) 进程管理
1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...
- Linux学习笔记(七) 查询系统
1.查看命令 (1)man 可以使用 man 命令名称 命令查看某个命令的详细用法,其显示的内容如下: NAME:命令名称 SYNOPSIS:语法 DESCRIPTION:说明 OPTIONS:选项 ...
- 进程间通信系列 之 命名管道FIFO及其应用实例
进程间通信系列 之 概述与对比 http://blog.csdn.net/younger_china/article/details/15808685 进程间通信系列 之 共享内存及其实例 ...
随机推荐
- CI框架篇之预热篇(1)
CodeIgniter 的基本都了解了,现在就开始预热,如果学习一门语言一样,我们最开始都是输出一个'HELLO WORLD'一样, 现在我们也通过输出这样一个内容,来了解基本的使用. CodeIgn ...
- c语言训练题:关于张三李四王五说谎的问题(此处用javascript实现)
(第一篇博文) 今天在一个交流群里见他们无聊,然后找到之前收藏的一些c语言题目放出去想让他们做,结果反倒是自己不会做,于是花了很多时间去想. 原题:张三说李四在说谎,李四说王五在说谎,王五说张三和李四 ...
- c# 获取MAC IP TCP列表
转载自baidu:http://hi.baidu.com/jackeyrain/item/ff94efcfd5cf3a3099b498e9 namespace Public { public clas ...
- Android - 向服务器发送数据(POST) - HTTPClient.
该篇文章主要说明使用Apache提供的HTTPClient,通过post方式,向服务器发送数据.由于有些东西在 Android - 向服务器发送数据(GET)中提到过,就不再重复. 一,Android ...
- A题笔记(7)
No. 1468 已知三角形的三条边求面积:海伦公式 S=√[p(p-a)(p-b)(p-c)] p=(a+b+c)/2 #include <cmath> cmath 是 c++ 语言 ...
- C#一些小技巧(二)
教你们怎么改配色方案,因为本人智障了很久,每次想改颜色的时候都会看到一大圈的选项,难以琢磨,但是智障了那么久终于被我找到了所有的关联. 首先,要告诉你们的是,其实C#里面要改的东西只有那么几个,但是注 ...
- 使用switch case语句来显示月份的对应天数
方法一:控制台输入月份 package com.liaojianya.chapter1; import java.util.Scanner; /** * This program demonstrat ...
- OSI 7层模型
协议:电脑与电脑通信之间的一种“约定”ois模式1,物理层2. 数据链路层3. 网络层4. 传输层5. 会话层6. 表示层7. 应用层发email为例 应用层:从用户输入完成所要发送的内容并点击“发送 ...
- 中国天气网接口返回json格式分析及接口(XML、图片接口)说明
实时天气: city "北京"//城市 cityid "101010100"//城市编码 temp "17&qu ...
- QueryRunner的使用
在相继学习了JDBC和数据库操作之后,我们明显感到编写JDBC代码并非一件轻松的事儿.为了帮助我们更高效的学习工作,从JDBC的繁重代码中解脱出来,老佟给我们详尽介绍了一个简化JDBC操作的组件——D ...