前面我们讲了进程间通信的一种方式,匿名管道
我们知道,匿名管道只能用于父子关系的进程之间。那么没有这种关系的进程之间该如何进行数据传递呢?

1.什么是命名管道

匿名管道是在缓存中开辟的输出和输入文件流的空间,只能用于父子关系的进程之间。因为父子进程的输入和输出文件描述符是一致的。
命名管道是一种实际存在的FIFO文件,称作“管道文件”,用于不同进程之间,命名管道进程间打开同一个FIFO文件,进行数据传递。
我们可以像普通文件一样操作FIFO文件。
不同进程,引用同一个FIFO文件,进行数据传递。

2.创建命名管道
mkfifo函数:创建一个命名管道

int mkfifo(const char *filename,mode_t mode);

filename:指定FIFO文件的名称
mode:指定文件的读写权限

3.访问命名管道
打开FIFO文件有四种方式:

open(const char *filename,O_RDONLY);
open(const char *filename,O_RDONLY|O_NONBLOCK);
open(const char *filename,O_WRONLY);
open(const char *filename,O_WRONLY|O_NONBLOCK);

需要注意的是,不能以O_RDWR模式打开FIFO文件,
因为这样一个进程写入的数据会被该进程读取,FIFO一般只用做单向的数据传递。

open函数的第二个参数,表示是读管道,还是写管道。
O_NONBLOCK表示FIFO管道的读写是非阻塞的,默认的话,是阻塞的。
那么何为阻塞呢?
一个进程写模式打开管道的时候,必须有另一个进程以读模式打开;
或读模式的时候,必须有另一个进程写写模式打开,否则该进程open函数阻塞,直到满足以上关系。

非阻塞,意味着open函数会立即返回,若没有其他进程以只读方式打开,open返回-1,并且FIFO也不会被打开。

4.FIFO管道使用示例
下例有两个程序,fifowrite.c和fiforead.c分别写管道和读管道。
fifowrite.c中将一个文本文件data.txt,写到管道。
fiforead.c中从管道读取数据,并写到dataformfifo.txt文件中。
程序使用了默认的阻塞模式。
示例代码如下:

fifowrite.c

#include<sys/types.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<limits.h>
int main()
{
const char *fifo_name = "/tmp/my_fifo";
int pipe_fd = -;
int data_fd = -;
int res = ;
const int open_mode = O_WRONLY;
char buffer[PIPE_BUF+];
if(access(fifo_name,F_OK)==-)
{
res = mkfifo(fifo_name,);
if(res!=)
{
fprintf(stderr,"could not create fifo\n");
exit(EXIT_FAILURE);
}
}
printf("process %d opening fifo O_WRONLY\n",getpid());
pipe_fd = open(fifo_name,open_mode);
data_fd = open("data.txt",O_RDONLY);
printf("process %d result %d\n",getpid(),pipe_fd);
if(pipe_fd!=-)
{
int bytes_read = ;
bytes_read = read(data_fd,buffer,PIPE_BUF);
while(bytes_read>)
{
res = write(pipe_fd,buffer,bytes_read);
if(res==-)
{
fprintf(stderr,"write error\n");
exit(EXIT_FAILURE);
}
bytes_read = read(data_fd,buffer,PIPE_BUF);
buffer[bytes_read]='\0';
}
close(pipe_fd);
close(data_fd);
}
else{
exit(EXIT_FAILURE);
}
printf("process %d finished.\n",getpid());
exit(EXIT_SUCCESS);
}

fiforead.c

#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>
#include<limits.h>
int main()
{
const char *fifo_name = "/tmp/my_fifo";
int pipe_fd = -;
int data_fd = -;
int res = ;
int open_mode = O_RDONLY;
char buffer[PIPE_BUF+];
int bytes_read = ;
int bytes_write = ;
memset(buffer,'\0',sizeof(buffer)); printf("process %d opening FIFO O_RDONLY\n",getpid());
pipe_fd = open(fifo_name,open_mode);
data_fd = open("dataformfifo.txt",O_WRONLY|O_CREAT,);
printf("process %d result %d\n",getpid(),pipe_fd);
if(pipe_fd!=-)
{
do{
res = read(pipe_fd,buffer,PIPE_BUF);
bytes_write = write(data_fd,buffer,res);
bytes_read +=res;
}while(res>);
close(pipe_fd);
close(data_fd);
}
else{
exit(EXIT_FAILURE);
}
printf("process %d finished,%d bytes read\n",getpid(),bytes_read);
exit(EXIT_SUCCESS);
}

输出结果:

我们在shell中输入命令 ls -l /tmp/my_fifo查看FIFO管道文件的属性

可以看到,FIFO文件生成了,第一个字符‘p’,表示该文件是一个管道文件。

5.多个进程同时写管道
当多个进程同时写管道时,读管道取得的数据是杂乱的。
此时,我们可以控制每个进程,当要写入的数据超过某个大小时,才写管道,另外要以阻塞的方式打开FIFO。确保写操作的原子性。

Linux进程间通信-命名管道的更多相关文章

  1. Linux - 进程间通信 - 命名管道

    1.命名管道的特点: (1)是管道,可用于非血缘关系的进程间的通信 (2)使用命名管道时,梁金成需要用路径表示通道. (3)命名管道以FIFO的文件形式存储于文件系统中.(FIFO:总是按照先进先出的 ...

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

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

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

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

  4. Linux进程间通信(一) - 管道

    管道(pipe) 普通的Linux shell都允许重定向,而重定向使用的就是管道. 例如:ps | grep vsftpd .管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准 ...

  5. linux进程间通信-有名管道(FIFO)

    有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...

  6. Linux - 进程间通信 - 匿名管道

    一.概念:进程间通信( IPC,InterProcess Communication) 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进城之间要交换数据必须通过内 ...

  7. Windows进程间通信--命名管道

    1 相关概述 命名管道(Named Pipes)是一种简单的进程间通信(IPC)机制.命名管道可以在同一台计算机的不同进程之间,或者跨越一个网络的不同计算机的不同进程之间的可靠的双向或单向的数据通信. ...

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

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

  9. Windows进程间通信—命名管道

    命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节.我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信.与Socket网络通信相比,命名管道不再需要编写身份验证的代码.将 ...

随机推荐

  1. Java(JVM运行时)各种内存区域详解及扩展

    本文整理于  Java内存与垃圾回收调优 Java 堆内存 从几个sample来学习Java堆,方法区,Java栈和本地方法栈 首先来一张图让我们理清楚java运行时状态: 诚然,如上图所示:java ...

  2. tip use view.isineditmode() in your custom views to skip code when shown in eclipse

    tip use view.isineditmode() in your custom views to skip code when shown in eclipse

  3. HackRF实现GPS欺骗教程

    硬件平台:HackRF One软件平台:MAC运行环境搭建系统平台:OS X 10.11 EI CapitanGPS终端:One Plus手机,飞行模式,仅GPS定位,GPS test App文章特点 ...

  4. php大力力 [008节]局部表量

    2015-08-23 php大力力008. php局部表量 开始写简单程序,遇到几个小困难障碍. 第一个:不要少写最后一个问号❓ <?php echo 'HELLO WORLD';?> 程 ...

  5. python 安装操作 MySQL 数据库.

    以ubuntu和mysql为例 检查自己的机器上面有没有安装数据库 xpower@xpower-CW65S:~$ sudo service mysql start [sudo] xpower 的密码: ...

  6. PHP数据类型和常量

    数据类型的转换    一种是强制转换            语法:setType(变量,类型).这个函数将原变量的类型转变                在赋值前使用(类型)的形式,不会改变原变量的类 ...

  7. linux命令:cat

    1:命令介绍: cat用来打印标准输入或连接文件.tac是其相反命令,从最后一行开始打印. 2:命令格式: cat [选项] 文件 3:命令参数: -A, --show-all           等 ...

  8. K Best(最大化平均数)_二分搜索

    Description Demy has n jewels. Each of her jewels has some value vi and weight wi. Since her husband ...

  9. 将List转换成DataTable

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  10. [图论]Dijkstra 算法小结

    Dijkstra 算法小结  By Wine93 2013.11 1. Dijkstra 算法相关介绍 算法阐述:Dijkstra是解决单源最短路径的算法,它可以在O(n^2)内计算出源点(s)到图中 ...