管道和FIFO(有名管道) (三)

FIFO

FIFO指代先进先出,first in first out,也称为有名管道。其是一个单向的(半双工)的数据流,每个FIFO有一个路径名与之关联,从而实现无亲缘关系的进程访问同一个FIFO。


FIFO由mkfifo函数创建
#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *pathname,mode_t mode);/*pathname 为文件路径名,是FIFO的名字。mode是文件权限位*/


管道与FIFO异同

  1. 管道只能用于有亲缘关系的进程,FIFO可用于无亲缘关系的进程(FIFO在文件系统中有一个名字)。
  2. 管道在所有进程最终关闭它之后自动消失。FIFO的名字则只能通过调用unlink才从文件系统中删除。
  3. 创建并打开管道:pipe         
  4. 创建FIFO:mkfifo         打开FIFO:open
  5. 对管道或FIFO的write总是向末尾添加数据,read总是从开头返回数据。


实现两个FIFO的客户-服务器例子




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

#define FIFO1 "/tmp/fifo.1"

#define FIFO2 "/tmp/fifo.2"

void client(int readfd,int writefd);
void server(int readfd,int writefd);

int main(int argc,char *argv[])

{

    int readfd,writefd;

    pid_t childpid;

    if((mkfifo(FIFO1,FILE_MODE) < 0 ) && (errno != EEXIST))/*创建两个FIFO*/

        printf("can not create %s\n",FIFO1);

    
    if((mkfifo(FIFO2,FILE_MODE) < 0 ) && (errno != EEXIST))

    {

        unlink(FIFO1);

        printf("can not create %s\n",FIFO2);

    }

    if ((childpid = fork()) == 0)/*子进程*/

    {

        readfd = open(FIFO1,O_RDONLY,0);/*读FIFO1*/

        writefd = open(FIFO2,O_WRONLY,0);/*写FIFO2*/

        server(feadfd,writefd);

        exit(0);

    }

    /*父进程*/

    writefd = open(FIFO1,O_WRONLY,0);/*写FIFO1*/

    readfd = open(FIFO2,O_WRONLY,0);/*读FIFO2*/


    client(readfd,writefd);

    waitpid(childpid,NULL,0);

    close(readfd);

    close(writefd);

    unlink(FIFO1);/*手动删除FIFO1/2*/

    unlink(FIFO2);


}

void client(int readfd,int writefd)/*参数分别为 pipe2[0],pipe1[1]*/  
  
{  
  
    size_t len;  
  
    ssize_t n;  
  
    char buff[MAXLEN];  
  
    fgets(buff,MAXLEN,stdin);/*从标准输入stdin中获取输入(一段路径名)放入buff*/  
  
    len = strlen(buff);  
  
    if(buff[len - 1] == '\n') /*删除由fgets存入的换行符*/  
  
        len--;  
  
    write(writefd,buff,len);/*将buff中内容写入管道pipe1[1] writefd,传输到子进程server*/  
  
    while((n = read(readfd,buff,MAXLEN)) > 0)/*从pipe[0] readfd中读取子进程server传输过来的内容放入buff,并显示到标准输出stdout*/  
  
        write(STDOUT_FILENO,buff,n);  
  
}  

void server(int readfd,int writefd)/*参数对应pipe1[0],pipe2[1]*/  
  
{  
  
    int fd;  
  
    ssize_t n;  
  
    char buff[MAXLEN+1];  
  
    if((n = read(readfd,buff,MAXLEN)) == 0)/*从管道pipe1[0] readfd中读取来自父进程client的输入并放入buff*/  
  
        printf("end-of-file while reading pathname\n");  
  
    buff[n] = '\n';  
	
    if((fd = open(buff,O_RDONLY)) < 0)/*open 打开client 通过管道传输过来的路径名*/  
  
    {  
  
        snprintf(buff+n,sizeof(buff) - n,"can not open %s\n",strerror(errno));  
  
        n=strlen(buff);  
  
        write(writefd,buff,n);/*打开失败,将错误信息写入管道writefd pipe2[1],传输至父进程client*/  
  
    }  
  
    else  
  
    {  
  
        while((n = read(fd,buff,MAXLEN)) > 0)/*打开成功,将路径名对应的文件中的内容读出到buff, 
 
                                               并写到管道writefd pipe2[1] 传输至父进程client */  
  
            write(writefd,buff,n);  
  
        close(fd);  
  
    }  
  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值