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的更多相关文章

  1. Linux 进程间通信(二) 管道

    Linux 进程间通信-管道 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及 ...

  2. linux 进程间通信 之fifo

    上一篇博客已经介绍了一种进程间通信的方式,但是那只是针对于有血缘关系的进程,即父子进程间的通信,那对于没有血缘关系的进程,那要怎么通信呢?  这就要创建一个有名管道,来解决无血缘关系的进程通信, fi ...

  3. Linux进程间通信(二) - 消息队列

    消息队列 消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据. 消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点(管道请查阅我的另一篇文章 ...

  4. Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

    Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

  5. Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

    Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

  6. Linux 进程间通信之管道(pipe),(fifo)

     无名管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 定义函数: int pipe(int f ...

  7. Linux进程间通信(二)

    信号 信号的概念 信号是Linux进程间通信的最古老的一种方式.信号是软件中断,是一种异步通信的方式.信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某个突发事件. 一旦产生信号 ...

  8. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()

    我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...

  9. Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)

    整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...

  10. Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()

    在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关 ...

随机推荐

  1. 【SpringCloud】第一篇: 服务的注册与发现(Eureka)

    前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...

  2. 【Java】Map转换器

    描述: 在控制层接收参数时候, 往往会出现Json格式需要转换为Bean. 通常一两个字段可以用new去save pojo, 但字段多的情况呢? 以下就是为了解决这个尴尬情况,  自己写一个转换工具类 ...

  3. 【转】Linux学习(1)-常用快捷键、文件管理和查询

    原文链接:http://www.cnblogs.com/zhaopei/p/7397402.html 有话要说 为什么要用Linux?要用Linux的原因太多,想说说不完啊. 如果你说用Linux只是 ...

  4. java调c# exe 程序,exe里写文件问题

    应用场景描述: java web程序,触发 调用c#写的后台exe程序,发现exe里写的文件找不到.单独在cmd命令行下执行exe没问题: 问题查找: 由于exe里获取文件路径错误导致: 解决方法: ...

  5. Flask 学习笔记(一)

    一.Web 服务器与 Web 框架 首先明确一下,要运行一个动态网页,我们需要 一个 Web 服务器来监听并响应请求,如果请求的是静态文件它就直接将其返回,如果是动态 url 它就将请求转交给 Web ...

  6. NO12——快速幂取模

    long long quickmod(long long a,long long b,long long m) { ; while(b)//用一个循环从右到左便利b的所有二进制位 { )//判断此时b ...

  7. 支持ie的时间控件 html

    连接:http://www.my97.net/demo/resource/2.4.asp#m248 下载测试:链接: https://pan.baidu.com/s/17AdRa2OTLPI7ndiA ...

  8. python基础之获取版本信息

    在工作中经常会需要确定使用的py的版本信息,以便适配更多的系统,达到更大的兼容性. 一般关于python的信息和参数都要调用sys模块,关于操作系统的信息和调用都要使用os模块 所以这次我们使用sys ...

  9. 团队作业4——第一次项目冲刺(Alpha版本)-第二篇

    项目冲刺——第二阶段 度过了敏捷冲刺,各个成员积极汇报各自的工作.好了,着手下一步规划! Mission 团队成员 任务 郭达  实现PHP后台的答题判分查看正确率 刘德培  编写博客 石浩洋  实现 ...

  10. PHP的报错级别并返回当前级别error_reporting()

    定义和用法:error_reporting() 设置 PHP 的报错级别并返回当前级别.函数语法:error_reporting(report_level) 如果参数 level 未指定,当前报错级别 ...