Linux命名管道及函数
管道(pipe)应用的一大局限是没有名字,只能用于具有亲缘关系进程之间的通信。而命名管道,也称FIFO,实质是一种文件类型,通过FIFO可以用于任何两个进程间的通信。
命名管道的创建
命令方式
在shell中可以使用mkfifo
命令创建一个命名管道,格式为:
mkfifo [option] name
其中option选项用于选择创建FIFO的模式,使用形式为-m mode
,mode为八进制模式,创建示例:
mkfifo -m 666 myfifo
创建之后可以在当前文件间看到新建的文件。
函数方式
FIFO管道可通过mkfifo()函数创建,函数原型为:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
创建成功返回0,出错返回1。函数第一个参数为普通的路径名,即创建后FIFO文件的名字,第二个参数与打开普通文件的open函数中的mode参数相同。
如果要创建的FIFO文件已经存在,则会返回EEXIST错误,因此在创建前应先检查是否创建成功,若文件已存在,只要调用打开FIFO的函数即可。
编程示例
创建一个命名管道,create_FIFO.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
mode_t mode = 0666;
if(argc != 2)
{
printf("USEMSG:create_FIFO{FIFO name}n");
exit(1);
}
if((mkfifo(argv[1], mode))<0)
{
perror("failed to mkfifo!n");
exit(1);
}
else
{
printf("you successfully create a FIFO name is: %sn", argv[1]);
}
return 0;
}
编译执行:
$ ./create_FIFO testFIFO
you successfully create a FIFO name is: testFIFO
上述程序使用mkfifo函数创建了一个名为“testFIFO”的命名管道。
此时再次执行:
C$ ./create_FIFO testFIFO
failed to mkfifo!
: File exists
由于要创建的FIFO已经存在,再次创建会提示创建失败。
命名管道的读写
一般的文件I/O函数均可用于FIFO操作,如open、close、read、write等,若要删除一个命名管道,则使用系统调用unlink。
编程示例
FIFO写入
向FIFO写入数据,write_fifo.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#define BUFES PIPE_BUF
int main(void)
{
int fd;
int n,i;
char buf[BUFES];
time_t tp;
char fifo_name[]="fifo1";
printf("My process ID: %dn", getpid());
// create a fifo
if(mkfifo(fifo_name, 0666) < 0)
{
printf("mkfifo failed, maybe there exist a same fifo filen");
//exit(1);
}
else
printf("mkfifo okn");
printf("...n");
// open the fifo, write only mode
if((fd=open(fifo_name, O_WRONLY))<0)
{
printf("Open failed!n");
exit(1);
}
else
printf("Open fifo ok!n");
for(i=0;i<5;i++)
{
time(&tp);// get current time
n=sprintf(buf,"write_fifo %d seconds %s", getpid(), ctime(&tp));
printf("Send msg: %s", buf);
// write to fifo
if((write(fd, buf, n+1)) < 0)
{
printf("Write failed!n");
close(fd);
exit(1);
}
sleep(2);
}
// close the fifo
close(fd);
// delete the fifo
unlink(fifo_name);
exit(0);
}
该程序首先创建一个名为fifo1的FIFO,如果已存在则直接调用open()函数打开,之后通过write()函数写入当前的时间内容到FIFO,最后使用close()函数关闭FIFO,并用unlink(函数删除FIFO。
FIFO读取
从FIFO读取数据 ,read_fifo.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#define BUFES PIPE_BUF
int main(void)
{
int fd;
int len;
char buf[BUFES];
mode_t mode = 0666;
printf("My process ID:%dn", getpid());
// open a fifo, read only mode
if((fd=open("fifo1", O_RDONLY))<0)
{
printf("Open failed!n");
exit(1);
}
// read the fifo
while((len=read(fd, buf, BUFES))>0)
printf("Read_fifo read:%s", buf);
// close the fifo
close(fd);
exit(0);
}
该程序首先调用open()函数打开FIFO,之后通过read()函数循环读取FIFO的内容,每次读取PIPE_BUF个字节,最后使用close()函数关闭FIFO。
测试
分别编译上述两个程序。测试之前先使用mkfifo命令创建一个名为fifo1的命名管道:
mkfifo -m 666 fifo1
然后打开两个shell窗口,依次运行write_fifo和read_fifo两个程序。
其中一个shell中运行写入程序:
$ ./write_fifo
My process ID: 2278
mkfifo ok
...
Open fifo ok!
Send msg: write_fifo 2278 seconds Tue Nov 26 09:49:09 2019
Send msg: write_fifo 2278 seconds Tue Nov 26 09:49:11 2019
Send msg: write_fifo 2278 seconds Tue Nov 26 09:49:13 2019
Send msg: write_fifo 2278 seconds Tue Nov 26 09:49:15 2019
Send msg: write_fifo 2278 seconds Tue Nov 26 09:49:17 2019
另一个shell中运行读出程序:
$ ./read_fifo
My process ID:2282
Read_fifo read:write_fifo 2278 seconds Tue Nov 26 09:49:09 2019
Read_fifo read:write_fifo 2278 seconds Tue Nov 26 09:49:11 2019
Read_fifo read:write_fifo 2278 seconds Tue Nov 26 09:49:13 2019
Read_fifo read:write_fifo 2278 seconds Tue Nov 26 09:49:15 2019
Read_fifo read:write_fifo 2278 seconds Tue Nov 26 09:49:17 2019
首先运行的write_fifo程序在执行到FIFO的open时会进入等待,直到read_fifo进程也执行的到open时,两进程间的FIFO通信开始。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- SRCMS 多处越权+权限提升管理员漏洞
- SAP Spartacus把指定产品添加到购物车的API
- MyBatis源码解析之基础模块—Plugin
- php框架slim架构上存在XXE漏洞(XXE的典型存在形式)
- 个人博客搭建
- 安全箱子的秘密
- Linux 机器 CPU 毛刺问题排查
- phpwind 利用哈希长度扩展攻击进行getshell
- dotnet 构建 SourceRoot items must include at least one top-level item when DeterministicSourcePaths is
- Magicodes.IE 2.4版本发布
- EC2磁盘扩容-DiskPressure
- 谈一谈php://filter的妙用
- 新型php漏洞挖掘之debug导致的安全漏洞(Edusoho)
- CVE-2016-3714 - ImageMagick 命令执行分析
- 知乎某处XSS+刷粉超详细漏洞技术分析