Linux 进程间通信之管道

进程之间的通讯之管道

目录

1.无名管道

2.有名管道

3.管道读写规则

1 无名管道


   管道是一种最基本的IPC机制,作用于父子进程之间,完成数据传递。
管道有以下特性:
1.其本质是一个伪文件(实为内核缓冲区)其本质是一个伪文件(实为内核缓冲区)
2.由两个文件描述符引用,一个表示读端,一个表示写端。
3.规定数据从管道的写端流入管道,从读端流出。
3.规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
无名管道的简单实现:


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

int main()
{
    int pipefd[2];
    pid_t pid;
    if (pipe(pipefd) == -1 )    
    {
        printf("pipe() err..\n");   
        return -1;
    }
    pid = fork();
    if (pid == -1)
    {
        printf("fork err..\n");
        return -1;
    }

    if (pid == 0)
    {
        close(pipefd[0]);
        write(pipefd[1], "hello hello....", 6);
        close(pipefd[1]);
        printf("child .....quit\n");

    } 
    else if (pid > 0 )
    {
        int len = 0; 
        char buf[100] = {0};
        close(pipefd[1]);
        len = read(pipefd[0], buf, 100);
        printf("len:%d, buf:%s \n", len , buf);

        close(pipefd[0]);
    }
    wait(NULL);
    printf("parent ..quit\n");
    return 0;
}

2.有名管道

命名管道也被称为FIFO文件,是一种特殊的文件。由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一。
有名管道实例
1.建立管道C语言实现 或者 shell指令 : mkfifo 文件名
C语言实现

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>

/*
利用管道,两个进程间进行文件复制。
fifow
读文件1.txt    
    写入管道
fifor   
    读管道
    写入2.txt文件
    */

int main(int argc, char *argv[])
{
    //建立管道文件
    int outfd = 0;

    //打开管道文件,准备写数据
    outfd = open("fifop", O_WRONLY | O_NONBLOCK);
    //outfd = open("pp", O_WRONLY ); //阻塞模式
    if (outfd == -1)
    {
        printf("infd open() err..\n");
        exit(0);
    }

    return 0;
}

写端

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>

/*
利用管道,两个进程间进行文件复制。
fifow
读文件1.txt    
    写入管道
fifor   
    读管道
    写入2.txt文件
    */

int main(int argc, char *argv[])
{
    //建立管道文件
    mkfifo("fifop", 0644);
    int infd;

    //按只读方式 打开现有文件
    infd = open("./1.txt", O_RDONLY);
    if (infd == -1)
    {
        printf("infd open() err..\n");
        exit(0);
    }
    int outfd;

    //打开管道文件,准备写数据
    //outfd = open("fifop", O_WRONLY | O_NONBLOCK);
    outfd = open("fifop", O_WRONLY ); //阻塞模式
    if (outfd == -1)
    {
        printf("infd open() err..\n");
        exit(0);
    }

    char buf[1024];
    int n = 0;
    //从文件中读数据写入管道文件
    while ( (n = read(infd, buf, 1024)) > 0)
    {
        write(outfd, buf, n);   
    }
    close (infd);
    close (outfd);


    printf("fifow 写管道文件 success\n");
    return 0;
}

读端

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>



int main(int argc, char *argv[])
{   
    //打开2.txt 准备写数据
    int outfd;
    outfd = open("./2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); //O_TRUNC 打开文件清空
    if (outfd == -1)
    {
        printf("open()  2.txt err..\n");
        exit(0);
    }


    //打开管道文件,准读数据
    int infd;
    infd = open("fifop", O_RDONLY);
    if (infd == -1)
    {
        printf("open err ... \n");
        exit(0);
    }

    char buf[1024];
    int n = 0;
    //从文件中读数据写入管道文件
    while ( (n = read(infd, buf, 1024)) > 0)
    {
        write(outfd, buf, n);   
    }
    printf("读管道文件是否失败。。。。\n");
    close (infd);
    close (outfd);
    unlink("fifop");


    printf("fifor 读管道文件 success\n");
    return 0;
}

3.管道读写规则

当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
当管道满的时候

O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
如果所有管道写端对应的文件描述符被关闭,则read返回0

如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE

当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。

当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值