进程间通信IPC——命名管道

命名管道

    • 1、基本概念
    • 2、创建
      • 1)命令行
      • 2)函数
    • 3、示例

1、基本概念

命名管道是一种特殊的文件类型,其存在于磁盘上,但是大小永远是0。
不同于匿名管道的是:

  • 可在同一台计算机的不同进程之间或在跨越网络的不同计算机的不同进程之间实现通信
  • 支持可靠的、单向或双向的数据通信
  • 命名管道只是让两个无关的进程之间建立起联系,一旦关系建立起来,与命名管道的文件不再有关
  • 命名管道FIFO(first input first output)总是遵循先进先出的原则,即第一个进来的数据会第一个被读走
  • 命名管道可以一个读端,多个写端;也可以多个写端,一个读端

服务器建立命名管道时给它指定一个名字,任何进程都可以通过该名字打开管道的另一端,根据给定的权限和服务器进程通信。

2、创建

1)命令行

通过执行以下命令即可创建命名管道:

mkfifo fifo_file_name

fifo_file_name 是要创建的命名管道文件名称。
进程间通信IPC——命名管道_第1张图片
如上图所示,可以看到命名管道fifo1,其大小为0

2)函数

#include
#include

int mkfifo(const char* filename, mode_t mode)

返回:
    成功:0
    失败:-1
参数:
	filename:创建的命名管道名称
	mode:命名管道的读写模式,与open函数中的mode相同
		O_RDONLY: 只读打开
    	O_WRONLY: 只写打开
    	O_RDWR : 读,写打开
    	这三个常量,必须指定一个且只能指定一个

命名管道创建完成后就可以使用,其使用方法与管道一样,区别在于:命名管道使用之前需要使用open()打开。
这是因为:命名管道是设备文件,它是存储在硬盘上的,而管道是存在内存中的特殊文件。

但是需要注意的是

  • 命名管道调用open()打开有可能会阻塞,但是如果以读写方式(O_RDWR)打开则一定不会阻塞;
  • 以只读(O_RDONLY)方式打开时,调用open()的函数会被阻塞直到有数据可读;
  • 如果以只写方式(O_WRONLY)打开时同样也会被阻塞,直到有以读方式打开该管道

3、示例

/*************************************************************************
    > File Name: read_fifo.c
    > Describe: 命名管道测试文件->读取文件
    > Author: hang
    > Mail: [email protected] 
    > Created Time: Thu 27 Feb 2018 08:19:34 PM CST
 ************************************************************************/

#include
#include
#include
#include
#include
#include

int main()
{
    int fd;
    int len;
    char buf[1024];
    if(mkfifo("fifo1", 0666) < 0 && errno!=EEXIST) // 创建FIFO管道
        perror("Create FIFO Failed");

    if((fd = open("fifo1", O_RDONLY)) < 0)  // 以读打开FIFO
    {
        perror("Open FIFO Failed");
        exit(1);
    }
    while((len = read(fd, buf, 1024)) > 0) // 读取FIFO管道
    {
        printf("Read message: %s", buf);
    }
    close(fd);  // 关闭FIFO文件
    
    return 0;
}
/*************************************************************************
    > File Name: write_fifo.c
    > Describe: 匿名管道测试文件->输入文件 
    > Author: hang
    > Mail: [email protected] 
    > Created Time: Thu 27 Feb 2018 08:17:26 PM CST
 ************************************************************************/

#include
#include   // exit
#include    // O_WRONLY
#include
#include     // time
#include

int main()
{
    int fd;
    int n, i;
    char buf[1024];
    time_t tp;
    printf("I am %d process.\n", getpid()); // 说明进程ID
    
    if((fd = open("fifo1", O_WRONLY)) < 0) // 已写打开一个FIFO
    {
        perror("Open FIFO Failed");
        exit(1);
    }
    for(i=0; i<20; ++i)
    {
        time(&tp);  // 取系统当前时间
        n=sprintf(buf,"Process %d's time is %s",getpid(),ctime(&tp));
        printf("Send message: %s", buf); // 打印
        if(write(fd, buf, n+1) < 0)  // 写入到FIFO中
        {
            perror("Write FIFO Failed");
            close(fd);
            exit(1);
        }
        sleep(1);  // 休眠1秒
    }
    close(fd);  // 关闭FIFO文件
    return 0;
}

程序运行结果:
进程间通信IPC——命名管道_第2张图片
进程间通信IPC——命名管道_第3张图片
上述例子可以扩展成 客户进程—服务器进程 通信的实例,write_fifo的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,read_fifo类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理:
进程间通信IPC——命名管道_第4张图片

参考:
1.《UNIX环境高级编程》
2.《UNIX网络编程》

你可能感兴趣的:(Linux系统网络编程,IPC,FIFO,命名管道,进程间通信)