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

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. EditText提示文字

    如图,在没有输入文字前,会显示提醒文字. 引用的是文本文件(strings.xml)中的对应文字 activity_main.xml对应的红色代码: <?xml version="1. ...

  2. oracle 10gwindow7安装添加内容

    F:\软件\database\stage\prereq\db\refhost.xml <!--Microsoft Windows 7 .Windows 8--> <OPERATING ...

  3. Python变量与常量

    变量是计算机内存中的一块区域,变量可以存储规定范围内的值,而且值可以改变.基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中.常量是一块只读的内存区域,常量一旦被初始化就不能被 ...

  4. poll函数和串口设置

    2015.1.24 今天星期六,多云,早晨8:17起床的,今天是来南京起床最迟的一天,因为昨晚睡得有点迟,今天又不用上课,整个人有点放松.收拾好来到教室,教室门没有开,胡明也到了,其他人还在宿舍睡觉, ...

  5. DB other operation

    A prepared statement is a feature used to execute the same/similar SQL statement repeatedlly with hi ...

  6. iOS开发:集成支付宝(遇见的坑和便捷撸代码)

    开发iOS最重要的就是支付了,天朝之内最常用的就是支付宝了,下面就以自己的经历说明如何集成支付宝+遇见的坑. 首先,集成支付宝最好别使用Cocoapods,很多人都说使用起来很方便,可是我每次只要使用 ...

  7. 待研究之iOS硬件调研

    1.磁力计 完成指南针 参考类:CLLocationManager,CLHeading 2.照相机 完成一个按钮点击拍照,拍照完使用照片,一个按钮打开系统相册 选择图片 参考类: UIImagePic ...

  8. 多线程编程4 - GCD

    一.简介 在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决方案.GCD在工作时会自动利用更多的处理器核心,以充分利用更强大的机器.GCD是Gr ...

  9. Python3 配置文件 解析

    /************************************************************************ * Python3 配置文件 解析 * 说明: * ...

  10. Shell 条件表达式汇总

    条件表达式 文件表达式 if [ -f  file ]    如果文件存在if [ -d ...   ]    如果目录存在if [ -s file  ]    如果文件存在且非空 if [ -r f ...