`
gstarwd
  • 浏览: 1484455 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

多进程通信方式一:管道(PIPE)

阅读更多
进程通信(IPC)的几种方式及比较
撰文:黄显国080416
 
难得闲暇,抽空学习了一下进程通信的知识,现将这几天的所学做一下总结,以备遗忘时参考。
 
进程通信的方式:
Linux 系统继承了三种系统的进程通信模式:
1、 基于system V IPC
2、 基于UNIX IPC
3、  基于POSIX IPC
同时还包含一种socket 进程间通信,不过这种是不同处理器系统之间的一种网络通信方式,不是我所关心的。
 
方式一:管道(PIPE
管道分无名管道与有名管道两种
1、  无名管道。
无名管道用于具有亲缘关系的父子进程,子子进程之间的通讯。它的实现函数有
int pipe(int fd[2]);
//fd[2] 为描述符数组,包含一个读描述符与一个写描述符,在使用管道通信时,关闭某些不需要的读或写描述符,建立起单向的读或写管道,然后用readwrite 像操作文件一样去操作它即可。
 
如图便是进程1 到进程2 的一个读管道。
以下是我写的一个pipe 的验证程序,分别在父进程和父子进程里向管道写数据,然后在子进程和子子进程里读数据,当尝试改变各子进程的sleep 时间以实现渴望的同步时,会发现结果很有趣。注意创建子进程时将复制父进程的管道。
 

 

/*******************************************************************************************/
//pipe.c
//frome the example, we can see:
//用pipe创建的无名管道,父子进程,子子进程之间都可以通信,由于read
//或write默认为阻塞,而进程与进程之间又有某种意义上的同步方法;
//故而可以从下面的程序中得到一些启示。
/*****************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
 
int main()
{
       int pipe_fd[2];
       char buf_r[100];
       char buf_rr[100];
       if(pipe(pipe_fd)<0)
       {
              printf("pipe create error\n");
              return -1;
       }
       else
              printf("pipe create success\n");
       printf("pipe_fd[0]=%d,pipe_fd[1]=%d\n",pipe_fd[0],pipe_fd[1]);
      
       if(fork()==0)//子进程
       {
              close(pipe_fd[1]);//关闭子进程的写描述符
              printf("fork()");
              //sleep(2);
              if(fork()==0)//子子进程
              {    
                     if(read(pipe_fd[0],buf_r,5)>0)
                            printf("BUF_R: in child child process,read from the pipe is %s\n",buf_r); 
                     close(pipe_fd[0]);
                     exit(0);
              }
              Else //子进程
              {
                     if(read(pipe_fd[0],buf_rr,3)>0)
                            printf("BUF_RR: in child parent process,read from the pipe is %s\n",buf_rr);
                     close(pipe_fd[0]);
                     exit(0);   
              }
       }
       else  //父进程
       {
              close(pipe_fd[0]);
              sleep(5);
              if(write(pipe_fd[1],"Hello ",5)!=-1)
                     printf("write1 parent pipe success\n"); 
              if(fork()==0)  //父子进程
              {
                     if(write(pipe_fd[1],"PIPE",5)!=-1)
                            printf("write parent child pipe success");     
                     close(pipe_fd[1]);  
                     exit(0);   
              }
              close(pipe_fd[1]);
              exit(0);
       }
}
 
2、  有名管道
有名管道可用于两个无关的进程之间的通信。它的实现函数是:
int mkfifo(const char *filename, mode_t mode)
//创建一个名为filename的管道,模式可选为读或写方式,阻塞或非阻塞方式等。
下面一个实例演示了mkfifo的使用。Fifo_read.c不断从管道文件里读数据,fifo_write.c往管道文件里写数据。改变sleep的值也会产生类似上面进程同步的问题,而会发现一些缓冲区的特性。
两个程序用gcc编译后在两个终端里运行。
//---------------------------------------------------------------------------------------------------
//fifo_read.c
//创建有名管道,演示两个不相关的进程之间的通信
//int mkfifo(const char *filename, mode_t mode)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
 
#define FIFO "/home/huang/myfifo"
 
int main(int argc,char **argv)
{
       int fd;
       int nread;
       char buf_r[100];
       if(mkfifo("/home/huang/myfifo",O_CREAT|O_EXCL)<0)//&&(errno!=EEXIST))
       {
              perror("mkfifo:");
              printf("cann't create fifoserver\n");
              return -1;
       }
       printf("Preparing for reading bytes...\n");
       fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
       if(fd==-1)
       {
              perror("open!\n");
              exit(1);
       }
       while(1)
       {
              memset(buf_r,0,sizeof(buf_r));
              if((nread=read(fd,buf_r,sizeof(buf_r)))==-1)
              {
                     if(errno==EAGAIN)
                            printf("no data yet\n");
              }
              printf("read %s from FIFO\n",buf_r);
              sleep(1);
       }
       pause();
       unlink(FIFO);
}
 
//------------------------------------------------------------------------------------------------------------------
//fifo_write.c
//创建有名管道,演示两个不相关的进程之间的通信
//int mkfifo(const char *filename, mode_t mode)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
 
#define FIFO "/home/huang/myfifo"
 
int main(int argc, char **argv)
{
       int fd;
       char w_buf[100];
       int nwrite;
       if(argc==1)
       {
              printf("please send some message\n");
              exit(1);   
       }
       fd=open(FIFO,O_WRONLY|O_NONBLOCK,0);
       if(fd==-1)
       {
              if(errno==ENXIO)
                     printf("open error;no reading process\n");
              perror("open:");
              return -1;
       }
       memset(w_buf,'a',sizeof(w_buf));
       printf("sizeof(w_buf)=%d\n",sizeof(w_buf));
       while(1)
       {
              if((nwrite=write(fd,w_buf,strlen(w_buf)))==-1)
              {
                     if(errno==EAGAIN)
                            printf("The FIFO has not been write yet.\n");
                     perror("write");
              //     else
                     //     printf("error in writting!\n");
              }
              else
                     printf("write %s to the FIFO\n",w_buf);
              sleep(2);
       }
       close(fd);
}
 
分享到:
评论

相关推荐

    进程间通信之无名管道(pipe) 完整代码

    进程间通信之无名管道(pipe) 注意: 1 只能用于具有亲缘关系的进程之间的通信 2 SIGPIPE信号的处理 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 ...

    进程间通信之有名管道(fifo) 完整代码

    进程间通信之有名管道(fifo) 注意: 如果只打开有名管道的一端 则系统将暂时阻塞打开进程 直到有另一个进程打开该管道的另一端 当前进程才会继续执行 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道...

    进程间通信之信号 sinal ) 完整代码

    七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 sinal 五 消息队列 message queue ) 六 信号量 semophore 七 套接字 socket 以上七种进程间通信的完整...

    管道通信命名管道通信

    1 管道通信 利用pipe 和lockf 系统调用 编写程序 实现同族进程间的通信 使用系统调用pipe 建立一条管道线;创建子进程P1 P2 … 子进程Pi分别向管道各写信息 而父进程则从管道中读出来自于各子进程的信息 实现进程...

    进程通信.doc

    进程通信 Linux进程间通信 一、进程间通信概述 进程通信有如下一些目的: A、数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 B、共享数据:多个进程想要操作共享数据...

    进程间通信之共享内存 shared memory 完整代码

    七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 sinal 五 消息队列 message queue ) 六 信号量 semophore 七 套接字 socket 以上七种进程间通信的完整...

    进程管道通信

    1)使用系统调用pipe()建立一条管道,系统调用fork()分别创建两个子进程,它们分别向管道写一句话,如: Child process1 is sending a message! Child process2 is sending a message! 2) 父进程分别从管道读出...

    QT进程多个管道通信,并与C#客户端同时多个通信

    QT多个命名管道通信,并与C#客户端同时多个通信, 同时已有C#的客户端与服务器的通信,QT与QT的通信,QT与C#的通信,只要把管道名改为一至即可。

    linux实现软中断通信和管道通信报告(含代码)

    使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话: Child process 1 is sending a message! Child process 2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕...

    VC利用管道和多线程实现进程间通信

    visual c++利用管道和线程实现进程间通信

    匿名管道与命名管道的使用

    系统负责两件事:一是写入管道的数据和读出管道的数据的顺序是相同的,二是数据不会在管道中丢失,除非某个进程过早的退出. 建立管道函数为 int pipe(int pipe[2]); //其中pipe[0]是读取数据的描述字,pipe[1]...

    一个命名管道通信示例,包含客户端和服务器端

    命名管道可以用于本机的进程间或网络上不同机器进程间通信。这是一个运用命名管道进行通信的例子。包含客户端和服务器端。

    命名管道进程通信Windows程序设计

    用命名管道实现进程间的通信,用类对命名管道的操作进行封装

    Windows系统编程之进程间通信

    管道(pipe)是用于进程间通信的共享内存区域。创建管道的进程称为管道服务器,而连接到这个管道的进程称为管道客户端。一个进程向管道写入信息,而另外一个进程从管道读取信息。 异步管道是基于字符和半双工的(即...

    基于管道的进程间通信的小实例

    这是个基于管道的进程间通信的实例,对VC++多线程编程的初学者很有作用

    Python进程的通信Queue、Pipe实例分析

    进程通信的概念 进程的资源空间是相互独立的,一般而言是不能相互访问的。但很多情况下进程间需要互相通信,来完成系统的某项功能。进程通过与内核及其它进程之间的互相通信来协调它们的行为。 通信方法: 数据...

    python实现多进程通信实例分析

    下面尽量以简单的方式介绍一下每一类通信方式,具体的细节可以参照文档使用; 1. 管道 先来看一下最简单、古老的一种IPC:管道。通常指的是无名管道,本质上可以看做一种文件,只存在于内存当中,不会存盘。不同进程...

    华中科技大学操作系统实验报告.docx

    编制一段程序,实现进程的管道通讯:使用系统调用pipe( )建立一条管道线;两个子进程分别循环向这条管道写一句话: Child 1 is sending a message! Child 2 is sending a message! 而父进程则循环从管道中读出信息...

    Python进程间通信 multiProcessing Queue队列实现详解

    创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。 Queue([maxsize])创建共享的进程队列。 参数 :maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。 底层队列...

    Linux通过匿名管道进行进程间通信

    这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据。 一、什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号“|”来使用...

Global site tag (gtag.js) - Google Analytics