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. 今日Linux下安装部署禅道

    我的linux系统是在虚拟机上安装的Ubuntu,禅道在官网www.zentao.net下载安装的开源版的linux64位,采用一键安装包安装.安装前要求:系统上不能有自己安装的mysql .下载的安 ...

  2. SQL 语句中 exists和not exists的用法

    exists       (sql       返回结果集,为真)   not       exists       (sql       不返回结果集,为真) 如下: 表A ID   NAME    ...

  3. CSP201503-1:图像旋转

    引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...

  4. Linux服务架设篇--ping命令

    工作原理: 向远程机发送包含一定字节数的ICMP数据包,如果能收到对方的回复的数据包,就表明网络是相通的,而且根据两个数据包的时间差,还可以知道相互之间网络链接的速度. 注意: 有些远程主机由于某种原 ...

  5. 论文翻译 - Multiagent Bidirectionally-Coordinated Nets Emergence of Human-level Coordination in Learning to Play StarCraft Combat Games

    (缺少一些公式的图或者效果图,评论区有惊喜) (个人学习这篇论文时进行的翻译[谷歌翻译,你懂的],如有侵权等,请告知) Multiagent Bidirectionally-Coordinated N ...

  6. kinit

    su tf$ kinit -k -t /tmp/tf.keytab tf/admin@SINO.COM

  7. kaldi常用文件查看指令

    目录 1. ark特征文件 2. FST文件 3. mdl模型文件 4. 决策树文件 5. ali.gz对齐文件 资料来自kaldi官方文档. 转载注明出处. 1. ark特征文件 copy-feat ...

  8. int,long,long long类型的范围

    [内置类型] int      -2147483648-2147483647  //现在编译器的int型是32位的,以前为16位的范围是-32768~32767 unsigned  int   0-4 ...

  9. Android Service 服务(二)—— BroadcastReceiver

    (转自:http://blog.csdn.net/ithomer/article/details/7365147) 一. BroadcastReceiver简介 BroadcastReceiver,用 ...

  10. Visual Studio 2012,创建工程Build Driver,基于纯Source Code.

    拿到一堆纯代码,怎么去Create Project,设置Include路径,lib路径,要不要Pre-compile技术,配置Project之间的依赖关系. SourcesConverter  Bas ...