【Linux】管道

【什么是管道】
(1)管道是Unix中最古老进程间通信的形式
(2)我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。

【匿名管道】( pipe )
管道是IPC最基本的一种实现机制。我们都知道在Linux下“一切皆文件”,其实这里的管道就是一个文件。管道实现进程通信就是让两个进程都能访问该文件。
管道的特征:
只提供单向通信,也就是说,两个进程都能访问这个文件,假设进程1往文件内写东西,那么进程2 就只能读取文件的内容。
只能用于具有血缘关系的进程间通信,通常用于父子进程建通信
管道是基于字节流来通信的
依赖于文件系统,它的生命周期随进程的结束结束(随进程)
其本身自带同步互斥效果

要实现管道,我们需了解两个函数:
(1)创建管道:
这里写图片描述
pipe—->创建一个匿名管道。
返回值:成功返回0,失败返回-1。

(2)创建子进程:
这里写图片描述
注:包含在头文件 “unistd.h” 中,无参数,返回值类型为 pid_t
返回值:调用成功将子进程的 pid 返回给父进程,失败返回-1给父进程。
注意:调用成功会有两个返回值,对于父进程,返回的是子进程的pid;对于子进程,返回的是0。

实例:
//从键盘读取数据,写入管道,读取管道,写到屏幕

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

int main()
{
    int fds[2];    //存放标识符,0为读,1为写。
    char buf[100];
    int len;

    if(pipe(fds)==-1)
        perror("make pipe"),exit(1);

    //read from stdin
    while(fgets(buf,100,stdin))
    {
        len=strlen(buf);
        //write into pipe
        if(write(fds[1],buf,len)!=len)
        {
            perror("write to pipe");
            break;
        }
        memset(buf,0x00,sizeof(buf));

        //read from pipe
        if((len=read(fds[0],buf,100))==-1)
        {
        perror("read from pipe");
        break;
        }

        //write to stdout
        if(write(1,buf,len)!=len)
        {
            perror("write to stdout");
            break;
        }
    }

    return 0;
}


【命名管道】

上述管道虽然实现了进程间通信,但是它具有一定的局限性:首先,这个管道只能是具有血缘关系的进程之间通信;第二,它只能实现一个进程写另一个进程读,而如果需要两者同时进行时,就得重新打开一个管道。
为了使任意两个进程之间能够通信,就提出了命名管道(named pipe 或 FIFO)。
1、与匿名管道的区别:提供了一个路径名与之关联,以FIFO文件的形式存储于文件系统中,能够实现任何两个进程之间通信。而匿名管道对于文件系统是不可见的,它仅限于在父子进程之间的通信。
2、 FIFO是一个设备文件,在文件系统中以文件名的形式存在,因此即使进程与创建FIFO的进程不存在血缘关系也依然可以通信,前提是可以访问该路径。
3、 FIFO(first input first output)总是遵循先进先出的原则,即第一个进来的数据会第一个被读走。

【命名管道的创建】:

1.可在命令行上创建:
$ mkfifo filename

2.在程序里创建:
int mkfifo (const char* filename , mode_t mode);
注释:filename 为管道名称;mode 为权限

实例:
//读取文件,写入命名管道

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

#define ERR_EXIT(m)\
    do\
    {\
      perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

int main(int argc,char* argv[])
{
    mkfifo("tp",0644);
    int infd;
    infd=open("abc",O_RDONLY);
    if(infd==-1)
        ERR_EXIT("open");

    int outfd;
    outfd=open("tp",O_WRONLY);
    if(outfd==-1)
        ERR_EXIT("open");

    char buf[1024];
    int n;
    while((n=read(infd,buf,1024))>0)
    {
        write(outfd,buf,n);
    }
    close(infd);
    close(outfd);
    return 0;
}

//读取管道,写入文件

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

#define ERR_EXIT(m)\
    do\
    {\
      perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

int main(int argc,char* argv[])
{
    int outfd;
    outfd=open("abc.bak",O_WRONLY | O_CREAT | O_TRUNC,0644);
    if(outfd==-1)
        ERR_EXIT("open");

    int infd;
    infd=open("tp",O_RDONLY);
    if(infd==-1)
        ERR_EXIT("open");

    char buf[1024];
    int n;
    while((n=read(infd,buf,1024))>0)
    {
        write(outfd,buf,n);
    }
    close(infd);
    close(outfd);
    unlink("tp");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值