Linux-进程间通信(二): FIFO
1. FIFO:
FIFO也被成为命名管道,因其通过路径关系绑定,可以用于任意进程间通信,而普通无名管道只能用于有共同祖先的进行直接通信;
命名管道也是半双工的,open管道的时候不要以读写方式打开,这种操作是未定义的;
2. FIFO创建:
#include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode); ret = 成功返回0,失败返回-
FIFO是一种文件类型,mode参数与open函数中的mode参数相同,并且一般文件的操作函数(close, read, write, unlink等)都以用于FIFO;
3. 非阻塞标志(O_NONBLOCK):
(1) 阻塞模式:只读open要阻塞到某个进程为写而打开此FIFO,只写open要阻塞到某个进程为读而打开此FIFO;
(2) 非阻塞模式:只读立即返回,如果没有进程为读而打开FIFO,则只写open返回-1,erron=ENXIO;
4. 一端关闭:
(1) 若读一个已经关闭写端的FIFO,则读取完数据后,会读到文件结束符,read返回0;
(2) 若写一个已经关闭读端的FIFO,则产生SIGPIPE;
5. 用途:
(1) FIFO由shell命令使用以便将数据从一条管道传送到另一条,而无需创建临时文件;
(2) FIFO用于客户进程和服务器进程进行数据传递;
6. 测试代码:两个进程间通信;
fifo_writer.c -- 向fifo中写入字串
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h> #define FIFO_NAME "/var/tmp/fifo_test"
#define BUF_LEN PIPE_BUF int main(int argc, char *argv[])
{
int pipeid = -;
int fifoid = -; char buffer[BUF_LEN] = { }; if (access(FIFO_NAME, F_OK) < ){
fifoid = mkfifo(FIFO_NAME, );
if (fifoid < ){
perror("mkfifo error\n");
return -;
}
} pipeid = open(FIFO_NAME, O_WRONLY);
if (pipeid < ){
perror("open pipeid error\n");
return -;
} int read_bytes = read(STDIN_FILENO, buffer, BUF_LEN);
if (read_bytes < ){
perror("read error\n");
close(pipeid);
return -;
} const char * buff_send = buffer;
int no_write_bytes = read_bytes;
while (no_write_bytes > ){
int n = write(pipeid, buff_send, no_write_bytes);
if (n < ){
perror("write error\n");
close(pipeid);
return -;
} no_write_bytes -= n;
buff_send += n;
} close(pipeid); return ;
}
fifo_reader.c -- 从fifo中读出字串
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h> #define FIFO_NAME "/var/tmp/fifo_test"
#define BUF_LEN PIPE_BUF int main(int argc, char *argv[])
{
int pipeid = -; char buffer[BUF_LEN] = { }; pipeid = open(FIFO_NAME, O_RDONLY); int n = read(pipeid, buffer, BUF_LEN - );
if (n < ){
perror("read error\n");
close(pipeid);
return -;
} write(STDOUT_FILENO, buffer, n); close(pipeid); return ;
}
7. 测试代码:多个客户端与服务器通信
模型如下图所示:

common.h--公共头文件
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h> #define SERVER_FIFO_NAME "/var/tmp/fifoServer"
#define CLIENT_FIFO_NAME "/var/tmp/fifoClient%d"
#define BUFF_SIZE PIPE_BUF
#define MSG_LEN 64
#define CLIENT_FIFO_NAME_LEN 64 typedef struct fifo_msg{
pid_t client_pid;
char msg[MSG_LEN];
}fifo_msg_t;
fifo_server.c
#include "common.h" int main(int argc, char *argv[])
{
int fifo_id = -;
int server_fifo_fd = -; if (access(SERVER_FIFO_NAME, F_OK) < ){
fifo_id = mkfifo(SERVER_FIFO_NAME, );
if (fifo_id < ){
perror("mkfifo error\n");
return -;
}
} server_fifo_fd = open(SERVER_FIFO_NAME, O_RDONLY);
if (server_fifo_fd < ){
perror("open fifo error\n");
return -;
} fifo_msg_t client_msg;
memset(&client_msg, , sizeof(client_msg));
int read_bytes = ; do {
read_bytes = read(server_fifo_fd, &client_msg, sizeof(client_msg));
if (read_bytes < ){
perror("read error\n");
close(server_fifo_fd);
return -;
} char *tmp_msg = client_msg.msg;
while (*tmp_msg){
*tmp_msg = toupper(*tmp_msg);
tmp_msg++;
} char client_fifo[CLIENT_FIFO_NAME_LEN] = { };
snprintf(client_fifo, CLIENT_FIFO_NAME_LEN - , CLIENT_FIFO_NAME, client_msg.client_pid); int client_fifo_fd = open(client_fifo, O_WRONLY);
if (client_fifo_fd < ){
perror("open client fifo error\n");
} write(client_fifo_fd, &client_msg, sizeof(client_msg));
printf("write to client:%d\n", client_msg.client_pid);
close(client_fifo_fd); } while (read_bytes > ); close(server_fifo_fd);
return ;
}
fifo_client.c
#include "common.h" int main(int argc, char *argv[])
{
pid_t client_pid = -;
int server_fifo_fd = -;
int client_fifo_fd = -; server_fifo_fd = open(SERVER_FIFO_NAME, O_WRONLY);
if (server_fifo_fd < ){
perror("open server fifo error\n");
return -;
} client_pid = getpid(); char client_fifo_name[CLIENT_FIFO_NAME_LEN] = {};
snprintf(client_fifo_name, CLIENT_FIFO_NAME_LEN - , CLIENT_FIFO_NAME, client_pid);
if (mkfifo(client_fifo_name, ) < ){
perror("mkfifo client error\n");
close(server_fifo_fd);
return -;
} fifo_msg_t client_msg;
memset(&client_msg, , sizeof(client_msg));
client_msg.client_pid = client_pid; #define TRY_TIMES 3
int times = ;
for (times = ; times < TRY_TIMES; times++){
snprintf(client_msg.msg, MSG_LEN - , "client_pid:%d\n", client_pid);
write(server_fifo_fd, &client_msg, sizeof(client_msg)); client_fifo_fd = open(client_fifo_name, O_RDONLY);
if (client_fifo_fd < ){
perror("open client fifo error\n");
close(server_fifo_fd);
unlink(client_fifo_name);
return -;
} int n = read(client_fifo_fd, &client_msg, sizeof(client_msg));
if (n > ){
printf("reveive msg from server:%s", client_msg.msg);
} close(client_fifo_fd);
} close(server_fifo_fd);
unlink(client_fifo_name);
return ;
}
Linux-进程间通信(二): FIFO的更多相关文章
- Linux 进程间通信(二) 管道
Linux 进程间通信-管道 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及 ...
- linux 进程间通信 之fifo
上一篇博客已经介绍了一种进程间通信的方式,但是那只是针对于有血缘关系的进程,即父子进程间的通信,那对于没有血缘关系的进程,那要怎么通信呢? 这就要创建一个有名管道,来解决无血缘关系的进程通信, fi ...
- Linux进程间通信(二) - 消息队列
消息队列 消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据. 消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点(管道请查阅我的另一篇文章 ...
- Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)
Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)
- Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
- Linux 进程间通信之管道(pipe),(fifo)
无名管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 定义函数: int pipe(int f ...
- Linux进程间通信(二)
信号 信号的概念 信号是Linux进程间通信的最古老的一种方式.信号是软件中断,是一种异步通信的方式.信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某个突发事件. 一旦产生信号 ...
- Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()
我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...
- Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()
在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关 ...
随机推荐
- SQL SERVER 的操作复习
一.数据库的创建(SQL语句)CREATE DATABASE AON PRIMARY --主文件组( NAME='A_data',--逻辑文件名 --物理文件名 FILENAME=' ...
- spring boot接口 支持https
1.拥有证书,可自己生成测试用javatool生成 keytool -keystore [keyname].jks -genkey -alias tomcat -keyalg RSA 接下来输入相关信 ...
- 第5讲——cin处理字符输入
本来这一讲应该是while.for.if之类的,但是,我们可是学过C的男人,再浪费时间搞这个??? 还不如学点C++中的新知识. cin对象支持3种不同模式的单字符输入,其用户接口各不相同. 下面我们 ...
- Week 1 Team Homework #3 from Z.XML-软件工程在北航
任务名称:软件工程在北航 任务要求:要求我们采访往届师兄师姐,收集他们对于软件工程这门课程的反馈.具体作业链接http://www.cnblogs.com/jiel/p/3311403.html 任务 ...
- css3 移入移出动画
css: /*css3 鼠标移入移出动画 底部出现阴影层文字叙述*/ *{;} .div1{width:300px;height: 300px;text-align: center; backgrou ...
- Python-爬取"我去图书馆"座位编码
原文地址:http://fanjiajia.cn/2018/11/22/Python-%E7%88%AC%E5%8F%96%E2%80%9D%E6%88%91%E5%8E%BB%E5%9B%BE%E4 ...
- DELPHI控件属性事件说明
常用DELPHI控件属性事件设置说明 常用DELPHI控件属性设置说明目录TForm Class TPanel组件 TToolBar Class TToolButton Class TTimer Cl ...
- 【bzoj4236】JOIOJI STL-map
题目描述 JOIOJI桑是JOI君的叔叔.“JOIOJI”这个名字是由“J.O.I”三个字母各两个构成的. 最近,JOIOJI桑有了一个孩子.JOIOJI桑想让自己孩子的名字和自己一样由“J.O.I” ...
- [luogu2617]Dynamic Rankings
题面在这里 description 动态区间第\(k\)大 data range \[n,m\le 10000,a_i,t\le 1e^9\] solution 前置技能:主席树,静态区间第\(k\) ...
- poj3347 Kadj Squares (计算几何)
D - Kadj Squares Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Su ...