7分钟学会匿名管道pipe()的使用(内附完整代码测试)

一、创建匿名管道:

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

作用:创建一个匿名管道,用来进程间通信;

参数:int pipefd[2]这个数组是一个传出参数;

        pipefd[0] 对应管道的读端;

        pipefd[1] 对应管道的写端;

返回值:

        成功 0;

        失败-1;

注意:匿名管道只能在具有公共祖先的进程(父与子进程、两个兄弟进程、亲戚之间)

二、查看管道缓冲大小的命令:ulimit -a

三、查看管道缓冲大小的函数:

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

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int main()
{
    int pipefd[2];
    int ret=pipe(pipefd);
    long size=fpanthconf(pipefd[0],_PC_PIPE_BUF)//专门用来读取pipe的内存
    printf("pipe size:%ld",size);
    return 0;
    
}

运行结果如下:

4096个字节=4K 

四、其特点为:

1、管道是一个在内核内存中维护的缓冲器;

2、管道拥有文件的特质:读和写操作。匿名管道没有文件实体,而有名管道有文件实体;

3、通过管道传递的数据是有顺序的,读的顺序和写的顺序是一致的;

4、管道中的数据传递方向是单向的,一端用于写入,另一端用于读取,半双工(单工:只能单向传输,如遥控器向电视发送信号,但电视不能给遥控器发送信号;双工:双向都能同时传输信号,如两个在打电话,一个说话的时候也不影响对方说话,双方都能同时收到对方的信息;半双工:一段时间内只能一个方向传输,如果这个方向传输完毕另一端也会反向传输过来,如对讲机);

5、从管道读数据是一次性的,数据一旦被读走,数据将会被抛弃,释放空间以便储存新的数据;

6、匿名管道只能在具有公共祖先的进程(父与子进程、两个兄弟进程、亲戚之间)使用。

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

六、代码实现:

1、首先制作一个简易的单向传输发送信号

  1 #include <unistd.h>
  2 #include <string.h>
  3 #include <sys/types.h>
  4 #include <sys/stat.h>
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 int main()
  8 {
  9         //在fork前创建管道
 10         int pipefd[2];//里边有0和1
 11         int ret=pipe(pipefd);
 12         if(ret==-1)
 13         {
 14                 perror("pipe:");
 15                 exit(1);
 16         }
 17         pid_t pid=fork();
 18         if(pid>0)
 19         {
 20                 //父进程
 21                 printf("i am parent process,pid:%d\n",getpid());
 25                 char buf[1024]={0};
 26                 while(1)
 27                 {
 28                     int len=read(pipefd[0],buf,sizeof(buf));//读取子进程发来的数据
 29                     printf("parent recv:%s,pid:%d\n",buf,getpid());
 34                 }
 35         }else if(pid==0)
 36         {       //子进程
 37                 printf("i am child process,pid:%d\n",getpid());
 38                 //向父进程发送数据
 39                 char * str="hello,i am child";
 41                 while(1)
 42                 {
 43                 write(pipefd[1],str,strlen(str));
 44                 sleep(1);
 48                 }
 49         }
 52         return 0;
 53 }

输出结果为:

 2、制作一个双向传输的代码

        在双向通信时一定要注意:子进程和父进程的读写顺序是不一样的,因为子进程要先向父进程发送数据后才能收到由父进程发来的数据,所以对子进程来说是先write(),再read()。而父进程是先接收数据,再给子进程发送数据,所以对父进程来说是先read(),再write(),否则会发生阻塞。

  1 #include <unistd.h>
  2 #include <string.h>
  3 #include <sys/types.h>
  4 #include <sys/stat.h>
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 int main()
  8 {
  9         //在fork前创建管道
 10         int pipefd[2];//里边有0和1
 11         int ret=pipe(pipefd);
 12         if(ret==-1)
 13         {
 14                 perror("pipe:");
 15                 exit(1);
 16         }
 17         pid_t pid=fork();
 18         if(pid>0)
 19         {
 20                 //父进程
 21                 printf("i am parent process,pid:%d\n",getpid());
 22
 23                 char *strs="i am parent process!";
 25                 char buf[1024]={0};
 26                 while(1)
 27                 {
 28                     int len=read(pipefd[0],buf,sizeof(buf));//读取来自子进程发来的数据
 29                     printf("parent recv:%s,pid:%d\n",buf,getpid());
 30                    //向子进程发送数据
 31                     write(pipefd[1],strs,strlen(strs));
 32                     sleep(1);
 34                 }
 35         }else if(pid==0)
 36         {       //子进程
 37                 printf("i am child process,pid:%d\n",getpid());
                 
 39                 char * str="hello,i am child";
 40                 char buff[1024]={0};
 41                 while(1)
 42                 {
 38                      //向父进程发送数据
 43                     write(pipefd[1],str,strlen(str));
 44                     sleep(1);
 45                     //读取父进程发送来的数据
 46                     int fd=read(pipefd[0],buff,sizeof(buff));
 47                     printf("child recv:%s,pid:%d\n",buff,getpid());
 48                 }
 49         }
 52         return 0;
 53 }

运行结果如下:

觉得好看就给个赞吧,笔芯。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值