《Linux C编程实战》笔记:有名管道

管道的一个问题就是没有名字,因此只能用于有亲缘关系的进程间通信。

有名管道(named pipe或FIFO)它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。有名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。FIFO总是按照先进先出的原则工作。

有名管道的创建与读写

Linux下有两种方法创建有名管道。一是在Shell下交互地建立一个有名管道。Shell下可使用mknod或mkfifo命令,比如:

mknod namedpipe

或者是在程序里用函数。

#include<sys/types.h>
#include<sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode);

参数中path为创建的有名管道的全路径名:mod为创建的有名管道的模式,指明其存取权限,和creat函数的参数是一个意思。dev为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会用到。这两个函数成功调用都返回0,失败都返回-1

umask(0);
if(mknod("tmp/fifo",S_IFIFO|0666,0)==-1){
    perror("mknod error!");
    exit(1);
}

S_FIFO|0666 指明创建了一个有名管道且存取权限为0666,即创建者,与创建者同组的,其他用户对该有名管道的访问权限都是可读可写,这方面在文件读写章节有介绍

有名管道创建后就可以使用了,有名管道和管道的使用方法基本是相同的。只是使用有名管道时,必须先调用open打开。因为有名管道是存在于硬盘上的文件,而管道是存在于内存中的特殊文件。

需要注意的事,调用open打开有名管道的进程可能会被阻塞。但如果同时用读写方式O_RDWR打开,则一定不会导致阻塞;如果以只读方式O_RDONLY打开,则调用open函数的进程将会被阻塞直到有写方式打开管道;同样以只写方式O_WRONLY打开也会阻塞直到有读方式打开管道。

示例程序1

演示有名管道在无亲缘关系的进程如何进行通信。示例包含两个程序

//procread程序
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#define FIFO_NAME "myfifo"
#define BUF_SIZE 1024
int main(int argc,char **argv,char **environ){
    int fd;
    char buf[BUF_SIZE];
    umask(0);
    fd=open(FIFO_NAME,O_RDONLY);
    read(fd,buf,BUF_SIZE);
    close(fd);
    exit(0);
}

这个代码就是很简单的文件读取,没什么好说的。

然后是写的程序,在这里创建了有名管道

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#define FIFO_NAME "myfifo"
#define BUF_SIZE 1024
int main(int argc,char **argv,char **environ){
    int fd;
    char buf[BUF_SIZE]="Hello procwrite,I come from process named procread!";

    umask(0);
    if(mkfifo(FIFO_NAME,S_IFIFO|0666)==-1){
        perror("mkfifo error!");
        exit(1);
    }
    if((fd=open(FIFO_NAME,O_WRONLY))==-1){
        perror("fopen error!");
        exit(0);
    }
    write(fd,buf,strlen(buf)+1);
    close(fd);
    exit(0);
}

先运行write进程,运行后处于阻塞状态,因为要等另一个进程以写方式打开有名管道,然后再另一个终端运行read,结果如下:

同时也有一个myfifo的文件。 

有名管道的应用实例

这回也同样创建两个FIFO来实现不同进程的全双工通信。下面的程序演示两个进程间的聊天程序。一个为server端,一个为client端。

server端:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#define FIFO_READ "readfifo"
#define FIFO_WRITE "writefifo"
#define BUF_SIZE 1024
int main(int argc,char **argv,char **environ){
    int wfd,rfd;//读写的管道
    char buf[BUF_SIZE];
    int len;
    umask(0);
    if(mkfifo(FIFO_WRITE,S_IFIFO|0666)){//服务器程序创建写管道
        printf("can't create fifo %s because %s",FIFO_WRITE,strerror(errno));
        exit(1);
    }
    umask(0);
    wfd=open(FIFO_WRITE,O_WRONLY);//服务器程序以写方式打开写管道
    if(wfd==-1){
        printf("open fifo %s error:%s",FIFO_WRITE,strerror(errno));
        exit(1);
    }
    while((rfd=open(FIFO_READ,O_RDONLY))==-1){//这是一个循环,当客户端程序创建读管道时才继续下去
        sleep(1);
    }
    while (1)
    {
        printf("Server:");
        fgets(buf,BUF_SIZE,stdin);//从标准输入(也就是终端)读入字符串
        buf[strlen(buf)-1]='\0';//从标准输入读的字符串最后会有\n,把它改成\0
        if(strncmp(buf,"quit",4)==0){//如果是quit,就结束进程
            close(wfd);
            unlink(FIFO_WRITE);//unlink在文件删除这个文章介绍过
            close(rfd);
            exit(0);
        }
        write(wfd,buf,strlen(buf));//写
        len=read(rfd,buf,BUFSIZ);//读
        if(len>0){
            buf[len]='\0';
            printf("Client:%s\n",buf);
        }
    }
    
}

client端:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
//注意这里的fifo_write和fifo_read和服务器程序不一样,其他就几乎没啥区别了
#define FIFO_WRITE "readfifo"
#define FIFO_READ "writefifo"
#define BUF_SIZE 1024
int main(int argc,char **argv,char **environ){
    int wfd,rfd;
    char buf[BUF_SIZE];
    int len;
    umask(0);
    if(mkfifo(FIFO_WRITE,S_IFIFO|0666)){
        printf("can't create fifo %s because %s",FIFO_WRITE,strerror(errno));
        exit(1);
    }
    while((rfd=open(FIFO_READ,O_RDONLY))==-1){
        sleep(1);
    }
    umask(0);
    wfd=open(FIFO_WRITE,O_WRONLY);
    if(wfd==-1){
        printf("open fifo %s error:%s",FIFO_WRITE,strerror(errno));
        exit(1);
    }

    while (1)
    {
        len=read(rfd,buf,BUFSIZ-1);
        if(len>0){
            buf[len]='\0';
            printf("Client:%s\n",buf);
        }
        printf("Client:");
        fgets(buf,BUF_SIZE,stdin);
        buf[strlen(buf)-1]='\0';
        if(strncmp(buf,"quit",4)==0){
            close(wfd);
            unlink(FIFO_WRITE);
            close(rfd);
            exit(0);
        }
        write(wfd,buf,strlen(buf));

    }
    
}

分两个终端去运行

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《C MySQL8.0数据库跨平台编程实战笔记》是一本介绍如何在不同平台上使用C语言和MySQL8.0数据库进行编程的实用指南。本书从数据库的基本概念开始讲解,包括数据库的设计、表的创建和管理,以及SQL语句的基本使用方法。然后深入探讨了C语言和MySQL8.0数据库的结合,通过示例代码演示了如何在不同操作系统上使用C语言连接和操作MySQL8.0数据库。 本书以实战为主,介绍了在Windows、Linux和MacOS等不同平台上使用C语言编写跨平台的数据库程序的方法。读者可以通过学习本书,掌握在不同平台上使用C语言和MySQL8.0数据库的技巧和方法。此外,本书还介绍了一些实用的编程技巧和调试方法,帮助读者更好地应用C语言和MySQL8.0数据库进行开发和调试。 作者通过丰富的实例和详细的讲解,使读者能够快速掌握使用C语言和MySQL8.0数据库进行跨平台编程的技能。不论是初学者还是有一定开发经验的读者,都可以从本书中获得丰富的知识和经验。本书内容通俗易懂,深入浅出,适合作为C语言和数据库编程的入门指南,也适用于数据库开发人员和C语言程序员作为进阶学习和实践的参考。 总之,《C MySQL8.0数据库跨平台编程实战笔记》是一本实用性强、内容丰富的技术书籍,对于想要学习C语言和MySQL8.0数据库跨平台编程的读者来说是一本难得的好书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值