【Linux之进程间通信】03.有名管道

文章介绍了Linux系统中的有名管道,作为进程间通信的一种方式,它允许无亲缘关系的进程进行通信。通过mkfifo函数创建有名管道,并提供了代码示例展示如何在两个独立进程中实现数据传输。有名管道的特点包括不占用磁盘空间,读写端需分别初始化,否则会阻塞,以及数据读取后会被删除等。
摘要由CSDN通过智能技术生成

 
【Linux之进程间通信】

项目代码获取:https://gitee.com/chenshao777/linux-processes.git
(麻烦点个免费的Star哦,您的Star就是我的写作动力!)

03.有名管道

上一个博客介绍了无名管道
无名管道的特点是:
1.只能在父子进程中使用
2.无名管道实际上是内核空间的一个队列
3.读取无名管道数据后,被读取的数据在管道中会被删除
4.无名管道写满是65536字节,写溢出的话会阻塞
5.无名管道为空时,读取会阻塞

那么如果如何在两个无亲缘关系的进程中进行通信呢?
可以使用 “有名管道


有名管道是Linux系统中七大文件类型之一
七大文件类型有

文件类型标识符
普通文件-
目录d
管道p
链接文件l
套接字s
字符文件c
块设备文件b

其中管道、套接字、字符文件、块设备文件都是不占用磁盘空间

回来继续介绍有名管道


有名管道的创建

int mkfifo(const char *pathname, mode_t mode);

需要包含头文件

#include <sys/types.h>
#include <sys/stat.h>

创建一个有名管道

#include <sys/types.h>
#include <sys/stat.h>
int main()
{
	省略......
	mkfifo("./myfifo", 0777);
	省略......
}

创建有名管道和使用fopen函数创建文件一样,也是要赋权限的,实际权限也是需要减去umask的
另外一种创建有名管道的方法,直接在命令行使用 mkfifo xxxx 命令

hc@hc-vm:~/Linux_ARM/git/linux-processes/03.有名管道$ mkfifo myfifo
hc@hc-vm:~/Linux_ARM/git/linux-processes/03.有名管道$ ls
03.mkfifo_read.c  03.mkfifo_write.c  myfifo  read  write
hc@hc-vm:~/Linux_ARM/git/linux-processes/03.有名管道$ ll
总用量 40
drwxrwxr-x 2 hc hc 4096 522 22:36 ./
drwxrwxr-x 6 hc hc 4096 522 21:22 ../
-rw-rw-r-- 1 hc hc  685 522 21:09 03.mkfifo_read.c
-rw-rw-r-- 1 hc hc 1372 522 21:11 03.mkfifo_write.c
prw-rw-r-- 1 hc hc    0 522 22:36 myfifo|
-rwxrwxr-x 1 hc hc 8536 522 21:07 read*
-rwxrwxr-x 1 hc hc 8576 522 21:08 write*
hc@hc-vm:~/Linux_ARM/git/linux-processes/03.有名管道$

可以发现有名管道文件是不占磁盘空间的


代码实例:使用有名管道实现两个无亲缘关系的进程通信,使得进程1先运行,进程2后运行
事先使用 mkfifo 命令创建一个 myfifo 有名管道
写管道进程1代码:
打开有名管道myfifo,然后写入数据1
然后输出三行数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

/* 
    事先用mkfifo命令创建一个有名管道
    创建有名管道,并写入数据
    通过有名管道,实现一个进程先打印,另一个后打印
    运行命令: ./write
    结果:写进程先运行,由于有名管道读端还没有运行,所以该进程会阻塞
        直到读进程运行,写进程输出 “创建好有名管道写端”,和三行数据
        接着写入一个数据到管道
        读进程读到数据后结束阻塞,接着输出三行数据
*/
int main(int argc, char *argv[])
{
    // /*创建有名管道文件*/
    // if(0 == mkfifo("./myfifo", 0777))
    // {
    //     printf("有名管道创建成功\n");
    // }else{
    //     printf("有名管道创建失败\n");
    //     return -1;
    // }

    /*打开有名管道文件,此时才会在内核中创建队列*/
    int fd;
    fd = open("./myfifo", O_WRONLY);
    if(fd > 0){
        printf("创建好有名管道写端, fd = %d\n", fd);
    }

    /*输出三行数据, 这里会阻塞,因为要等另一个进程创建好有名管道读端*/
    for(int i = 0; i < 3; i++)
    {
        printf("first process\n");
    }
    sleep(2);
    char data = 1;
    /*写入数据*/
    write(fd, &data, 1);

    close(fd);

    return 0;
}

读管道进程2代码:
打开myfifo管道,读取一个字节数据
判断是否为1,若为1,则输出三行数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

/* 
    打开有名管道,读出数据
    运行命令: ./read
*/
int main(int argc, char *argv[])
{
    /*打开有名管道文件,此时才会在内核中创建队列*/
    int fd;
    fd = open("./myfifo", O_RDONLY);
    if(fd > 0){
        printf("创建好有名管道读端, fd = %d\n", fd);
    }

    char data = 0;
    /*读数据*/
    read(fd, &data, 1);
    printf("读取到管道数据为 %d\n", data);
    while(data == 0);

    /*输出三行数据*/
    for(int i = 0; i < 3; i++)
    {
        printf("second process\n");
    }

    close(fd);

    return 0;
}

实验结果:

  1. 先运行写管道进程1,发现没有任何输出,因为此时有名管道只初始化了写端,进程1等待进程2初始化读端;
  2. 接着运行读管道进程2,发现进程1打印了 “创建好有名管道写端, fd = 3”和三行数据
  3. 接着延时2秒后进程2打印 “创建好有名管道读端, fd = 3”和三行数据
  4. 最后两个进程都结束运行

可以看出有名管道的特点如下:

1.如果只初始化了管道的读写其中一端,则会阻塞,直到另一端初始化成功;
2.有名管道可以在两个无亲缘关系的进程间进行通信;
3.有名管道可普通文件一样,创建的时候可以进行权限的设置;
4.有名管道不占用磁盘空间

另外,其他特性均和无名管道相同
5.内核空间的一个队列
6.读取管道数据后,被读取的数据在管道中会被删除
7.管道写满是65536字节,写溢出的话会阻塞
8.管道为空时,读取会阻塞

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值