linux 管道_linux进程间通信----管道篇(三)----有名管道

先给自己打个广告,本人的微信公众号正式上线了,搜索:张笑生的地盘,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题。

一 what

前面一篇文章《linux进程间通信----管道篇(二)----无名管道》,我们谈到了无名管道,今天这篇文章我们来谈谈有名管道。

所谓有名管道,顾名思义,就是在内核中存在一个文件名,表明这是一个管道文件。

在此引申出一些扩展知识,linux中存在7种类型的文件,分别如下:

文件类型	文件特点
普通文件	标识符 ‘-’ ,用open方式创建
目录文件	标识符 ‘d’ ,用mkdir方式创建
链接文件	标识符 ‘l’, la -s, 又可以分为软链接,硬链接
管道文件	标识   ‘p’, 用mkfifo创建
socket文件	标识符 ‘s’
字符设备文件	标识符 ‘c’
块设备文件	标识符 ‘b’

其中有名管道文件、字符设备文件、块设备文件、套接字(socket)文件不占磁盘空间。

二 why

介绍了有名管道的基础概念之后,我们会问为什么需要有名管道?它能实现什么目的呢?

我们在前面的一篇文章中指出,无名管道只能用于父子进程,或者具有亲缘关系的进程间通信。如果是两个毫无关系的进程,相互间需要管道的方式来通信,要如何实现呢?这就是有名管道的作用,它可以实现这个目的。

三 how

3.1 如何创建有名管道

函数形式 : int mkfifo(const char * filename, mode_t mode)
功能 :创建管道文件
参数 :管道文件文件名,权限,创建的文件权限仍然和umask有关系
返回值 : 成功返回0,失败返回-1

注意:mkfifo并没有在内核中生成一个管道,只是在用户空间生成了一个有名管道文件

3.2 创建有名管道示例代码

#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"

int main(int argc, char *argv[])
{
    int ret;
    
    ret = mkfifo("./myfifo", 0777);
    if (ret < 0) {
        printf("create myfifo failn");
        return -1;
    }
    printf("create myfifo sucessn");
    
    return 0;
}

编译并运行上面的程序代码,会发现在当前目录下生成一个有名管道文件myfifo

7a4298e72ff05e0c98d73a31d2638634.png

3.3 利用有名管道进行相互将通信

我们知道了如何创建有名管道之后,就可以利用有名管道实现两个任意进程间通信了,如下

(a)进程A代码

/* 先在进程A中创建一个有名管道3rd_fifo,权限是0777
 * 然后以写方式打开这个有名管道文件,并向其中写入一个值
 * 在另外一个进程中以只读方式打开这个有名管道文件,并读取这个值
 */
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include "fcntl.h"

int main(int argc, char *argv[])
{
    int i, ret, fd;
    char p_flag = 0;
    
    /* 创建有名管道 */
    if (access("./3rd_fifo", 0) < 0) {   //先判断有名管道文件是否存在,不存在需要先创建
        ret = mkfifo("./3rd_fifo", 0777);
        if (ret < 0) {
            printf("create named pipe failn");
            return -1;
        }
        printf("create named pipe sucessn");
    }
    
    /* 打开有名管道,以写方式打开 */
    fd=open("./3rd_fifo", O_WRONLY);
    if (fd < 0) {
        printf("open 3rd_fifo failn");
        return -1;
    }
    printf("open 3rd_fifo sucessn");

    for (i = 0; i < 5; i++) {
        printf("this is first process i=%dn", i);
        usleep(100);
    }
    p_flag = 1;
    sleep(5);
    write(fd, &p_flag, sizeof(p_flag));

    while(1);
    return 0;
}

(b)进程B代码

/* 
 * 在本进程中以只读方式打开这个有名管道文件,并读取这个值
 */
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include "fcntl.h"

int main(int argc, char *argv[])
{
    int i;
    int fd=open("./3rd_fifo", O_RDONLY);
    char p_flag = 0;
    
    if (fd < 0) {
        printf("open 3rd_fifo failn");
        return -1;
    }
    
    printf("open 3rd_fifo sucessn");
    read(fd, &p_flag, sizeof(p_flag));
    while(!p_flag);
    for (i = 0; i < 5; i++) {
        printf("this is second process i=%dn", i);
        usleep(100);
    }

    while(1);
    return 0;
}

分别编译并运行

gcc 

运行结果,我们发现等A进程运行结束(打印都完成之后),B进程才会运行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值