前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux命名管道及函数

Linux命名管道及函数

作者头像
xxpcb
发布2020-08-04 15:31:27
2.6K0
发布2020-08-04 15:31:27
举报

管道(pipe)应用的一大局限是没有名字,只能用于具有亲缘关系进程之间的通信。而命名管道,也称FIFO,实质是一种文件类型,通过FIFO可以用于任何两个进程间的通信。

命名管道的创建

命令方式

在shell中可以使用mkfifo命令创建一个命名管道,格式为:

代码语言:javascript
复制
mkfifo [option] name

其中option选项用于选择创建FIFO的模式,使用形式为-m mode,mode为八进制模式,创建示例:

代码语言:javascript
复制
mkfifo -m 666 myfifo

创建之后可以在当前文件间看到新建的文件。

函数方式

FIFO管道可通过mkfifo()函数创建,函数原型为:

代码语言:javascript
复制
#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:

代码语言:javascript
复制
#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: %s\n", argv[1]);
    }
    return 0;
}

编译执行:

代码语言:javascript
复制
$ ./create_FIFO testFIFO
you successfully create a FIFO name is: testFIFO

上述程序使用mkfifo函数创建了一个名为“testFIFO”的命名管道。

此时再次执行:

代码语言:javascript
复制
C$ ./create_FIFO testFIFO
failed to mkfifo!
: File exists

由于要创建的FIFO已经存在,再次创建会提示创建失败。

命名管道的读写

一般的文件I/O函数均可用于FIFO操作,如open、close、read、write等,若要删除一个命名管道,则使用系统调用unlink。

编程示例

FIFO写入

向FIFO写入数据,write_fifo.c:

代码语言:javascript
复制
#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: %d\n", getpid());

   // create a fifo
   if(mkfifo(fifo_name, 0666) < 0)
   {
       printf("mkfifo failed, maybe there exist a same fifo file\n");
       //exit(1);
   }
   else
       printf("mkfifo ok\n");

   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:

代码语言:javascript
复制
#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:%d\n", 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的命名管道:

代码语言:javascript
复制
mkfifo -m 666 fifo1

然后打开两个shell窗口,依次运行write_fifo和read_fifo两个程序。

其中一个shell中运行写入程序:

代码语言:javascript
复制
$ ./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中运行读出程序:

代码语言:javascript
复制
$ ./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通信开始。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农爱学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 命名管道的创建
    • 命令方式
      • 函数方式
        • 编程示例
        • 命名管道的读写
          • 编程示例
            • FIFO写入
            • FIFO读取
            • 测试
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档