2.11-12匿名管道概述和父子进程通过匿名管道通信

ls | wc -l 中的|就是运用了管道把两个命令之间连接起来,把前面一个命令运行的指令的结果通过管道传给后面那一个命令

有名/匿名管道共同的特点:

 

管道的两端分别对应了两个文件描述符

匿名管道一般用在有关系的进程间通信,有名管道一般用在没有关系的进程间的通信

单工:遥控器发射信号给电视机,电视机不能发射信号给遥控器

双工:两个人之间打电话是互相通的,同时可以听到互相的数据

半双工:同一个时间只能往一个方向,方向是两头都可以但同一时间只能进行一个

Q:为什么匿名管道只能用于有关系的进程通信?

A:

由于父子进程共享文件描述符所以可以用同一个管道进行通信。

管道的数据结构:环形队列 

管道的使用函数:

/*
    #include <unistd.h>
    int pipe(int pipefd[2]);
        功能:创建一个匿名管道,用来进程间通信。
        参数:int pipefd[2] 这个数组是一个传出参数
            pipe[0]对应的是管道的读端
            pipe[1]对应的是管道的写端
        返回值:
            成功返回0,失败返回-1
    管道默认是阻塞的:如果管道没有数据,read阻塞,如果管道满了,write阻塞

    注意:匿名管道只能用于具有关系之间的进程通信,比如父子进程,兄弟进程
*/
//子进程发送数据给父进程,父进程读取到数据输出
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    //在fork之前创建管道
    int pipefd[2];
    int ret=pipe(pipefd);
    if(ret==-1){
        perror("pipe");
        exit(0);
    }

    //创建子进程
    pid_t pid=fork();
    if(pid>0){
        //父进程
        printf("i am parent process,pid : %d\n",getpid());
         //从管道的读取端读取数据
        char buf[1024]={0};
        while(1){
            int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
            printf("parent recv : %s, pid : %d\n",buf,getpid());


            char *str="hello,i am parent";
            write(pipefd[1],str,strlen(str));
            sleep(1);
        }
        
    }else if(pid==0){
        //子进程
        printf("i am child process,pid : %d\n",getpid());
        char buf[1024]={0};
        while(1){
            char *str="hello,i am child";
            write(pipefd[1],str,strlen(str));
            sleep(1);

            int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
            printf("child recv : %s, pid : %d\n",buf,getpid());
        }
       
    }
    return 0;
}

这里用了sleep使得父子进程相互切换才做到了父子进程互相通信,一般管道通信不用sleep也一般是一个流向

/*
    #include <unistd.h>
    int pipe(int pipefd[2]);
        功能:创建一个匿名管道,用来进程间通信。
        参数:int pipefd[2] 这个数组是一个传出参数
            pipe[0]对应的是管道的读端
            pipe[1]对应的是管道的写端
        返回值:
            成功返回0,失败返回-1
    管道默认是阻塞的:如果管道没有数据,read阻塞,如果管道满了,write阻塞

    注意:匿名管道只能用于具有关系之间的进程通信,比如父子进程,兄弟进程
*/
//子进程发送数据给父进程,父进程读取到数据输出
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    //在fork之前创建管道
    int pipefd[2];
    int ret=pipe(pipefd);
    if(ret==-1){
        perror("pipe");
        exit(0);
    }

    //创建子进程
    pid_t pid=fork();
    if(pid>0){
        //父进程
        printf("i am parent process,pid : %d\n",getpid());
         //从管道的读取端读取数据
        
        //关闭写端
        close(pipefd[1]);
        char buf[1024]={0};
        while(1){
            int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
            printf("parent recv : %s, pid : %d\n",buf,getpid());


            //char *str="hello,i am parent";
            //write(pipefd[1],str,strlen(str));
            //sleep(1);
        }
        
    }else if(pid==0){
        //子进程
        
        //关闭读端
        close(pipefd[0]);
        printf("i am child process,pid : %d\n",getpid());
        char buf[1024]={0};
        while(1){
            char *str="hello,i am child\n";
            write(pipefd[1],str,strlen(str));
            
            //sleep(1);

         //   int len=read(pipefd[0],buf,sizeof (buf));//如果管道里没有数据那么会阻塞
         //   printf("child recv : %s, pid : %d\n",buf,getpid());
         //   bzero(buf,1024);
        }
       
    }
    return 0;
}

pipe size = 512 * 8 = 4k

可以用ulimit -p 修改

/*
    #include <unistd.h>
    long fpathconf(int fd, int name);

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

int main(){
    
    int pipefd[2];
    int ret=pipe(pipefd);

    long size=fpathconf(pipefd[0],_PC_PIPE_BUF);//获取管道的大小
    printf("pipe size : %ld\n",size);
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值