有名管道及其实例1

本文介绍了有名管道(FIFO)的概念及其实现方式,并通过具体的代码示例展示了如何利用有名管道进行进程间通信。有名管道突破了无名管道仅能在父子进程间通信的限制,实现了任意进程之间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.介绍
前面的无名管道博文中,我们看到了创建两个管道可以实现进程间的全双工通信,那么同样也可以创建两个FIFO(有名管道)来实现不同进程间的全双工通信。
1.为什么引入有名管道?
我们通常所说的管道为无名管道或者匿名管道,管道没有名字,因此,只能在有亲缘关系的进程间(父子进程)实现通信,有名管道的出现突破了该限制,它是一个设备文件,它提供一个路径名与FIFO关联,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问这个路径也可以实现通信。
2.创建有名管道
mknod/mkfifo
shell中的创建方式

mknod 名字 pipe
mkfifo 名字

函数创建方式

(1)
int mknod(const char *path, mode_t mode, dev_t dev);
参数mode的选择
Name      Description
S_IFIFO   FIFO-special
S_IFCHR   Character-special (non-portable)
S_IFDIR   Directory (non-portable)
S_IFBLK   Block-special (non-portable)
S_IFREG   Regular (non-portable)
If  mode  is  not S_IFIFO or dev is not 0, the behavior of mknod() is unspecified.
举例:
mknod("/tmp/fifo", S_IFIFO | 0666, 0)
(2)
int mkfifo(const char *pathname, mode_t mode);
mkfifo()  makes  a  FIFO  special  file with name pathname.  mode specifies  the  FIFO's  permissions.
所以只需要填写管道的权限就型
举例
mkfifo("/tmp/fifo", 0666);

3.使用有名管道
与无名管道的使用方法基本相同,只是需要先调用open函数将其打开。因为有名管道终究是在硬盘上的文件,而无名管道只是存在内存上的特殊文件。
注意open()的阻塞情况
1.以只写方式打开,阻塞直到有读方式打开管道
open(“/tmp/fifo”, O_WRONLY);
2.以只读方式打开,阻塞直到有写方式打开管道
open(“/tmp/fifo”, O_RDONLY);
3.同时读写方式打开,一定不阻塞。
open(“/tmp/fifo”, O_RDWR);

二.代码演示
1.server.c

#include"utili.h"

int main()
{
    char sendbuf[MAX_MSG_LEN];
    char recvbuf[MAX_MSG_LEN];
    int res = mkfifo(FIFO_WRITE, 0666);
    if(res == -1)
    {
        perror("mkfifo WRITE");
        exit(EXIT_FAILURE);
    }
    //以只写方式打开,会阻塞到有读方式打开管道
    int wfd = open(FIFO_WRITE, O_WRONLY);
    if(wfd == -1)
    {
        perror("open WRITE");
        exit(EXIT_FAILURE);
    }
    //以只读方式打开,会阻塞到有写方式打开管道
    int rfd = open(FIFO_READ, O_RDONLY);
    if(rfd == -1)
    {
        perror("open READ");
        exit(EXIT_FAILURE);
    }
    while(1)
    {
        printf("Ser:>");
        scanf("%s", sendbuf);
        if(strcmp(sendbuf, "quit") == 0)
        {
             close(wfd);
             unlink(FIFO_WRITE);
             close(rfd);
             exit(EXIT_SUCCESS);
        }
        write(wfd, sendbuf, strlen(sendbuf)+1);

        read(rfd, recvbuf, MAX_MSG_LEN);
        printf("Cli:>%s\n", recvbuf);
    }
}

2.client.c

#include"utili.h"

int main()
{
    char recvbuf[MAX_MSG_LEN];
    char sendbuf[MAX_MSG_LEN];
    int wfd, rfd;
    int res = mkfifo(FIFO_READ, 0666);
    if(res == -1)
    {
        perror("mkfifo READ");
        exit(EXIT_FAILURE);
    }
    //server的写对应client读
    rfd = open(FIFO_WRITE, O_RDONLY);
    if(rfd == -1)
    {
        perror("open READ");
        exit(EXIT_FAILURE);
    }
    wfd = open(FIFO_READ, O_WRONLY);
    if(wfd == -1)
    {
        perror("open WRITE");
        exit(EXIT_FAILURE);
    }
    while(1)
    {
        read(rfd, recvbuf, MAX_MSG_LEN);
        printf("Ser:>%s\n", recvbuf);
        printf("Cli:>");
        scanf("%s", sendbuf);
        if(strcmp(sendbuf, "quit") == 0)
        {
             close(rfd);
             unlink(FIFO_READ);
             close(wfd);
             exit(EXIT_SUCCESS);
        }
        write(wfd, sendbuf, strlen(sendbuf)+1);
    }
}

3.公共头文件
utili.h

#ifndef _UTILI_H_
#define _UTILI_H_

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

#define FIFO_READ "readfifo"
#define FIFO_WRITE "writefifo"
#define MAX_MSG_LEN 256

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值