第4章 管道与FIFO

4.1 概述

管道只在亲缘进程间使用,FIFO在任意进程间使用

4.2 管道

#include <unistd.h>
int pipe(int fd[2])

fd[0]用来读管道,fd[1]用来写管道

1)命令who | sort | lp中的管道:

2)管道实现文件服务器与客户端:

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <error.h>

#define MAXLINE 1024

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

int main()
{
    int fd1[2];
    int fd2[2];
    pipe(fd1);
    pipe(fd2);
    int pid;
    if( (pid = fork()) < 0)
    {
        fprintf(stderr,"fork error\n");
        exit(-1);
    }
    if(pid > 0)
    {
        close(fd1[1]);
        close(fd2[0]);
        server(fd1[0],fd2[1]);
        exit(0);
    }
    close(fd1[0]);
    close(fd2[1]);
    client(fd2[0],fd1[1]);
    waitpid(pid,NULL,0);
    exit(0);
}

void client(int readfd,int writefd)
{
    size_t len;
    char buf[MAXLINE];
    fgets(buf,MAXLINE,stdin);
    len = strlen(buf);
    if(buf[len-1] == ‘\n‘)
          --len;
    write(writefd,buf,len);
    while( (len = read(readfd,buf,MAXLINE)) > 0)
          write(STDOUT_FILENO,buf,len);
}

void server(int readfd,int writefd)
{
    char buf[MAXLINE];
    ssize_t n;
    if( (n = read(readfd,buf,MAXLINE)) ==0)
    {
        fprintf(stderr,"error\n");
        exit(-1);
    }
    buf[n] = ‘\0‘;
    int fd;
    if( (fd = open(buf,O_RDONLY)) < 0)
    {
        snprintf(buf+n,sizeof(buf)-n,"can‘t open: %s\n",strerror(errno));
        n = strlen(buf);
        write(writefd,buf,n);
    }
    else
        while( (n = read(fd,buf,MAXLINE)) > 0)
            write(writefd,buf,n);
    close(fd);
}

4.3 popen和pclose函数

#include <stdio.h>
FILE *popen(char *cmd,char *type)
int pclose(FILE *fp)

popen函数创建另外一个进程执行cmd,并在调用进程与创建进程之间建立一个单向管道,管道的一端与返回的FILE对象绑定

type为"w",FILE对象与管道的写端绑定,cmd的标准输入为管道的读端

type为"r",FILE对象与管道的读端绑定,cmd的标准输出为管道的写端

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINE 1024
int main()
{
        char buf[MAXLINE];
        fgets(buf,MAXLINE,stdin);
        int n = strlen(buf);
        if(buf[n-1] == ‘\n‘)
                --n;
        char cmd[MAXLINE];
        snprintf(cmd,MAXLINE,"cat %s",buf);
        FILE *fp = popen(cmd,"r");
        while(fgets(buf,MAXLINE,fp) != NULL)
                fputs(buf,stdout);
        exit(0);
}

4.4 FIFO

FIFO又称命名管道

#include <sys/stat.h>
#include <sys/types.h>
int mkfifo(char *pathname,mode_t mode)

FIFO实现文件服务器和客户端

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

int main(int argc,char *argv[])
{
    if(mkfifo("./fifo1",S_IRUSR|S_IWUSR) < 0)
    {
        fprintf(stderr,"mkfifo error\n");
        exit(-1);
    }
    if(mkfifo("./fifo2",S_IRUSR|S_IWUSR) < 0)
    {
        fprintf(stderr,"mkfifo error\n");
        exit(-1);
    }
    int pid;
    if( (pid = fork()) < 0)
    {
        fprintf(stderr,"fork error\n");
        exit(-1);
    }
    if(pid == 0)
    {
        int fd1 = open("./fifo1",O_RDONLY);
        int fd2 = open("./fifo2",O_WRONLY);
        server(fd1,fd2);
        exit(0);
    }
    int fd1 = open("./fifo1",O_WRONLY);
    int fd2 = open("./fifo2",O_RDONLY);
    client(fd2,fd1);
    waitpid(pid,NULL,0);
    exit(0);
}

4.5 管道、FIFO的阻塞与非阻塞

时间: 2024-12-21 07:50:40

第4章 管道与FIFO的相关文章

第4章 管道和FIFO

4.1 管道 管道是由pipe函数创建的,提供一个单向数据流. 头文件 #include <unistd.h> 函数原型 int pipe(int fd[2]); 返回值 成功则为0,出错则为-1 函数功能 该函数返回两个文件描述符:fd[0]和fd[1].fd[0]用来读操作,fd[1]用来写操作 说明 管道只能用于有亲缘关系进程间通讯.要实现非亲缘关系进程间通讯用有名管道FIFO 4.2 管道实现半双工通讯 实现的步骤: (1)创建管道(fd[0]和fd[1]) (2)fork (3)父进

第四章:管道与FIFO

4.1:概述 管道是最初的Unix IPC形式,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限在于没有名字,从而只能由亲缘关系的进程使用.这一点随FIFO的加入得改正. 本章讲述管道和FIFO的创建与使用.我们使用一个简单的文件服务器例子,同时查看一些客户-服务器程序设计问题:IPC通道需要量.迭代服务器与并发服务器.字节流与消息接口. 4.2:一个简单的客户-服务器例子 下图所示的客户-服务器例子在本章和第六章中都要用,我们用它来分析说明管道.FIFO和Sys

进程间通信 ---- 管道与FIFO 用法技巧

1.管道的创建 1.1 mkfifo(const char *pathname,mode_t mode); 函数已隐含指定O_CREAT|O_EXCL,所以它要么创建一个新的FIFO,要么返回EEXIST错误(已存在). 所以在创建已存在FIFO或新的FIFO,应该先调用mkfifo,并检查返回值 是否是EEXIST错误,若是EEXIST错误,则调      用open函数. 2.FIFO或管道读写 2.1对管道或FIFO的write 总是往末尾添加数据,对管道或FIFO的read总是从头开始读

进程间通信(一)——管道和FIFO

1. 概述 管道没有名字,适用于有亲缘关系的进程间. FIFO指first in first out,有一个路径名与之关联,从而允许无亲缘关系的进程间使用.亦称:命名管道named pipe. 两者都是单向数据流(半双工管道),具有随进程的持续性,数据都是先进先出,在进程间通信不需要某种形式的同步. 2.管道 #include <unistd.h> int pipe(int fd[2]): 返回:成功0,出错-1: 返回两个文件描述符:fd[0]打开来读,fd[1]打开来写. 典型使用: (1

Linux下进程间通信之命名管道(FIFO)

匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信.在命名管道(FIFO)提出后,该限制得到了克服.FIFO不同于pipe在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够相互通信. FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出. Linux下有两种方式创建FIFO,一是在shell下交互的建立一个命名管道,二是在程序中使用系统函

Linux环境编程之IPC进程间通信(四):管道和FIFO比较

系统加于管道和FIFO的唯一限制是: 1.OPEN_MAX 一个进程在任意时刻打开的最大描述符数.可以通过调用sysconf函数查询. 2.PIPE_BUF 可原子地写往一个管道或FIFO的最大数据量.Posix任务它是一个路径名变量,它的值可以随指定的路径名而变化,因为不同的路径名可以落在不同文件系统上,而这些文件系统可能有不同的特征.所以PIPE_BUF可通过pathconf函数取得. pipeconf.c #include <stdio.h> #include <stdlib.h&

Linux IPC之管道和FIFO

导言:管道是UNIX系统上最古老的IPC方法,管道提供了一种优雅的解决方案:给定两个运行不同程序的进程,在shell中如何让一个进程的输出作为另一个进程的输入?管道可以用来在相关(一个共同的祖先进程创建管道)进程之间传递数据.FIFO是管道概念的一个变体,它们之间的一个重要差别在于FIFO可以用于任意进程间的通信. 概述 每个shell用户都对在命令中使用管道比较熟悉,例如,统计一个目录中文件的数目: ls | wc -l 解释:为了执行上面的命令,shell创建了两个进程来分别执行ls和wc(

管道和FIFO

管道和FIFO 管道(pipe) 管道在Unix及Linux进程间通信是最基础的,很容易理解.管道就像一个自来水管,一端注入水,一端放出水,水只能在一个方向上流动,而不能双向流动.管道是典型的单向通信,即计算机网络中所说的“半双工”.管道又名匿名管道,所以只能用在具有公共祖先的进程之间使用,通常使用在父子进程之间通信.通常是父进程创建一个管道,然后fork一个子进程,此后父子进程共享这个管道进行通信. 管道由pipe函数创建,函数原型如下: #include<unistd.h> int pip

MiS603开发板 第十一章 CY7C68013A Slave FIFO回传输

作者:MiS603开发团队 日期:20150911 公司:南京米联电子科技有限公司 论坛:www.osrc.cn 网址:www.milinker.com 网店:http://osrc.taobao.com EAT博客:http://blog.chinaaet.com/whilebreak 博客园:http://www.cnblogs.com/milinker/ MiS603开发板 第十一章 CY7C68013A Slave FIFO回传输 CY7C68013A提供了强大和灵活的外部接口通信方式,