linux 进城 管道丢数据,Linux进程间通信-命名管道

前面我们讲了进程间通信的一种方式,匿名管道。

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

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

#include

#include

#include

#include

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

#include

#include

#include

#include

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);

}

输出结果:

8191440fcc2d48ffd721a4eeee5b39fd.png

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

7062b058b2619d300c31cfbd7ab801cc.png

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

5.多个进程同时写管道

当多个进程同时写管道时,读管道取得的数据是杂乱的。

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

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

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

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

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

Linux 进程间通信(二) 管道

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

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

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

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

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

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

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

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

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

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

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

Windows进程间通信—命名管道

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

随机推荐

wpf telerik中的book控件

下载 telerik中的书本控件,仅供学习使用.

xshell xftp

xshell : http://www.netsarang.com/xshell_download.html xftp:http://www.netsarang.com/products/xfp_ov ...

IOS XML解析

<?xml version = "1.0"  encoding ="utf-8"?> 小黄人 ...

pentaho cde 选择性的显示多列数据

在业务需求中,有时候会有这种需要,就是查出来可多列数据,而我只想画出来其中的一列或者说某一列,而pentaho会默认画出查出来的所有数据,而不断的更改数据源又太麻烦,这时就要用到resders方法了. ...

javascript正则表达式&lpar;一&rpar;——语法

前言 js中类RegExp类表示正则表达式,具有强大的模式匹配.文本检索和替换功能.正则表达式的模式规则是由一个字符序列组成,包括所有字母和数字在内,大多数的字符都是按照直接量匹配字符,某些特殊字符并 ...

CTF---Web入门第六题 因缺思汀的绕过

因缺思汀的绕过分值:20 来源: pcat 难度:中 参与人数:6479人 Get Flag:2002人 答题人数:2197人 解题通过率:91% 访问解题链接去访问题目,可以进行答题.根据web题一 ...

linux 记录用户操作日志

将以下加入到/etc/profile 最后 history USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]/ ...

第 8 章 容器网络 - 072 - 一文搞懂各种 Docker 网络

Docker 起初只提供了简单的 single-host 网络,显然这不利于 Docker 构建容器集群并通过 scale-out 方式横向扩展到多个主机上. 跨主机网络方案: Docker Over ...

vs code配置git

在项目目录执行 git init 修改.git文件夹下的config文件 [core] repositoryformatversion = 0 filemode = false bare = fals ...

HTTPS数据传输过程简介

HTTPS数据传输过程 1.客户端发起HTTPS连接握手 2.服务端收到HTTPS握手连接请求,与客户建立握手过程,和TCP的三次握手类似,并发送一系列的加密算法组合给客户端,与客户端协商加密算法组合 ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值