Linux应用程序学习之进程通信之管道

Linux进程通信之管道

Linux中进程通信方式,即IPC通信方式主要有以下七种:

(1)无名管道(pipe)

(2)有名管道(FIFO)

(3)信号

(4)消息队列

(5)共享内存

(6)信号量

(7)套接字(Socket)

在后面的学习中,我将重点学习这些知识,这一节我学习了无名管道和有名管道,在此将学习总结写下来。

         在进行linux管道通信编程之前,我们首先要了解其通信原理,Linux管道通信模式是一个进程在管道的尾部写入数据,另外一个进程从管道的头部读出数据。管道包括无名管道和有名管道两种,前者只能用于父子进程间的通信,后者则可用于运行于同一系统中的任意两个进程间的通信。管道的通信有如下特点:

1、管道通讯是单向的,有固定的读端和写端。

2、数据被进程从管道读出后,在管道中该数据就不存在了。

3、当进程去读取空管道的时候,进程会阻塞。

4、当进程往满管道写入数据时,进程会阻塞。

5、管道容量为64KB。

在linux系统中,无名管道一旦创建完成后,就会产生两个端子,分为读端

和写端,此时操作无名管道就相当于是操作文件,采用文件描述符来描述无名管道的两端。

下面我们就来看看具体的函数操作吧,在linux中,可以用下面的函数来创建一个无名管道

int pipe(intpipefd[2]);

该函数如果成功创建一个管道,则返回0,否则返回-1,其参数是一个int

类型的数组,这个数组并非是作为一个传递值,而是作为一个接收的数组,当我们调用这个函数的时候,系统会把分配的描述符存放在这个数组中,pipefd[0]是表示读端的描述,pipefd[1]表示写端的描述,如此,有了描述符,我们便可以像操作一个文件一样来操作无名管道了,下面我就一个实例程序来模拟一下无名管道之间的通讯:

#include<stdio.h>
#include<unistd.h>
void main()
{
     pid_t pid;
     int pipefd[2];
     char buf[8];
    
    pipe(pipefd);   //创建一个管道,必须在创建子进程前创建
    
     pid = fork();
       
     if(pid >0)   
         {
             write(pipefd[1] , "hello" , 6); //向管道写入数据
             wait();   //等待子进程读取管道数据退出
             exit(0);
         }
                
     else if(pid == 0)
         {
             read(pipefd[0] , buf , 6); //读取管道中的数据
             printf("the data is %s\n" , buf);//打印读取到的数据
             exit(0);
         }   
}

程序中必要的位置已做了详细的注释需要再次说明的是这是无名管道通讯方式,只有父子进程间才可以使用这种方式。分析下上面的程序,最终结果应该是什么?根据我们前面的分析介绍,应该不难得出,这个程序应该会打印出

                      the data is hello

在linux下运行这个程序,可以很容易得到这个结果。

 

    上面说了无名管道,下面就说一下有名管道,有名管道又称为FIFO文件,因此对有名管道的操作也可以像对文件一样,使用诸如open,write,read等函数方法。但是FIFO文件和普通的文件还是有部分区别的:

读取Fifo文件的进程只能以“O_RDONLY”方式打开fifo文件,而写Fifo文件的进程只能以“O_WRONLY”方式打开fifo文件;Fifo文件里面的内容读取后就消失了,但是普通文件里面的内容读取后还存在。

   下面我们就来看看如何创建一个FIFO文件,创建FIFO类似于创建普通文件,Linux中为我们提供了下面的函数来创建一个FIFO;

       intmkfifo(const char *pathname , mode_t mode);

这个函数成功创建一个FIFO文件后就返回0否则返回-1,该函数第一参数指的是文件创建的路径,这个文件路径必须不存在,不然创建不成功,第二个参数之前我们有接触过,就是在讲文件编程时open函数的一个参数,其表示一个文件选项,用来标注创建的文件是“只读”、“只写”等等。创建完一个FIFO文件后,我们就可以用open函数打开它。另外我们还有一个函数,叫unlink,该函数可用于删除一个FIFO文件,其原型如下:

             int unlink(const char *pathname);

  参数为待删除文件的路径。下面我们就来用一个程序实例看看我们FIFO文件的用法,这个实例是任意两个进程采用有名管道来进行通信,因此我们需要新建两个文件:

   向管道写数据的pipename.C文件代码如下:

</pre><pre name="code" class="cpp">#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
void main()
{
       int fd;
       int result = 2;
       fd = open("/home/share/fun_call/fifl",O_WRONLY);
       if(fd == -1)
         {   printf("name pipe is not exist,we will create it\n");
            result = mkfifo("/home/share/fun_call/fifo" , O_WRONLY);
              if(result!=0)
                {
                    printf("create named pipe fail result = %d\n",result);
                    return -1;
                }
       fd= open("/home/share/fun_call/fifo" , O_WRONLY);
} 
向管道读取数据的代码如下:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
voidmain()
{
    int fd;
    char buf[15];
    fd =open("/home/share/fun_call/fifo" , O_RDONLY);
        
      read(fd , buf , 15);      
       printf("readthe buf is %s\n" , buf);      
      close(fd);
      unlink("/home/share/fun_call/fifo");   
}

        以上两个程序,pipename.c向管道写入了hello fifo 11个字节的数据,readfifo.c就是读取这个数据,如果运行readfifo.c的编译后的可执行文件打印出了hell fifo则说明我们实现了利用有名管道在两个进程间通信。需要说明的是,在运行读数据可执行文件之间,我们首先要执行写入的可执行文件,也就是pipename.c编译后产生的文件,这时候由于无人读取,界面会进入阻塞状态等待其它进程来读取,因此我们要重启一个命令行界面来运行readfifo.c生产的可执行文件。运行结果如下:

 

可见我们的程序确实实现了任意进程间通过有名管道来进行通信。

   总之,对于管道的操作,我们完全可以把它看做是对两个文件来进行操作,以上便是Linux应用编程中有关管道的知识,纰漏之处希望得到广大好友的指正。

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值