`
gstarwd
  • 浏览: 1536776 次
  • 性别: 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 四 信号 ...

    进程的管道通信

    管道通信是进程间通信(IPC, Inter-Process Communication)的一种方式,尤其在多进程环境下,用于不同进程之间交换信息。在Linux系统中,管道是一种半双工的通信方式,数据只能单向流动,且数据被所有读取者共享。 ...

    实验四:Linux下进程管道通信.docx

    此外,实验也强调了在多进程环境中正确处理并发写入和读取的重要性,以避免数据竞争和丢失。 总结起来,管道通信是操作系统中进程间通信的一个重要方法,它不仅限于父子进程,也可以在有共同祖先的进程之间共享。...

    进程的管道通信实验 操作系统 课程设计

    1. **管道的创建与连接**:使用`pipe()`系统调用可以创建一个管道,该调用返回两个文件描述符,一个用于写入,另一个用于读取。通常,父进程创建管道,然后通过`fork()`创建子进程,将读写端口分别传递给子进程。 2...

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

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

    操作系统实验四 进程的管道通信 实验报告

    总结起来,这个实验加深了对操作系统中进程通信的理解,尤其是管道通信的概念。通过实践,我们学习了如何创建管道、读写管道以及如何在父子进程中协调通信。这对于理解和开发多进程应用程序,特别是在需要进程间数据...

    进程间通信,通过Pipe管道实现

    管道是由内核创建的一个特殊文件,两个进程可以通过这个文件进行通信:一个进程作为写端,将数据写入管道;另一个进程作为读端,从管道中读取数据。管道的容量有限,一旦满,写端将被阻塞,直到读端读取一些数据释放...

    实验一 进程通信——管道和信号实验报告.doc

    本次实验是关于操作系统中的进程通信,主要涉及了进程的创建、控制、以及多种通信方式,包括信号通信和管道通信。通过实验,目的是加深对进程概念的理解,掌握并发执行的本质,并学习如何解决进程间的互斥问题。实验...

    C# 进程间通信:命名管道方式例子

    总的来说,C#中的命名管道是一种强大的进程间通信机制,尤其适用于在同一台机器上运行的进程之间的通信。它提供了一种低延迟、高效率的解决方案,可以传输各种复杂的数据结构。在.NET 2.0框架环境下,结合`System.IO...

    linux平台下实现进程间通信的一种:pipe

    其中,管道(Pipe)是一种简单而有效的IPC方式,它允许父子进程或者兄弟进程之间进行单向通信。本篇文章将深入探讨Linux下的管道通信,并以C语言为例,解析如何创建和使用管道。 首先,管道的特性是半双工通信,即...

    进程的管道通信实验 操作系统

    管道通信是早期Unix系统中引入的一种半双工通信方式,它允许数据在一个方向上流动,即数据只能从一个进程写入,由另一个进程读出。 首先,我们需要了解什么是进程。进程是程序在计算机中的一次动态执行,它是操作...

    linux进程间的通信:匿名管道

    然而,对于更复杂的多进程通信,可能需要考虑使用其他IPC机制,如命名管道(有名管道)、消息队列、共享内存或套接字等。 总的来说,Linux中的匿名管道是进程间通信的一个基础工具,虽然功能相对有限,但在特定场景...

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

    在Windows操作系统中,进程间通信可以使用剪贴板、DDE、OLE等方式,而管道是其中一种新的简便的通信机制。 管道是一种共享内存区,进程可以将共享消息放到这里。由于管道专用于进程间的通信,Win32API提供了一组...

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

    总之,通过理解和应用QT的命名管道机制,开发者可以构建出高效、可扩展的多进程通信系统,同时能够与其他语言的应用(如C#)无缝对接,提升系统的整体性能和灵活性。在设计这样的系统时,应充分考虑并发控制、数据...

    vc利用命名管道进行通信namedpipe

    命名管道(Named Pipe)是Windows操作系统提供的一...总之,"vc利用命名管道进行通信namedpipe"这个主题涉及了Windows系统下的进程间通信技术,通过理解和应用这些知识,开发者可以构建出能有效通信的多进程应用程序。

    实验 Linux进程通信的参考答案

    实验 Linux 进程通信的参考答案展示了 Linux 中进程通信的机制和方式,包括信号机制、管道通信机制和多进程并发执行。这些机制和方式是 Linux 编程中非常重要的概念,了解它们对于编写高效、可靠的程序非常重要。

    进程的软中断通信和管道通信

    进程通信的实现方法有很多,包括软中断通信和管道通信。本文将详细介绍这两种通信方法。 一、软中断通信 软中断通信是指进程之间通过软中断信号来实现通信的方法。在 Linux 系统中,软中断信号可以通过 signal() ...

    嵌入式系统中的进程间通信:深入管道与命名管道

    管道是一种半双工通信方式,仅存在于内存中,适用于具有公共祖先的进程间通信。而命名管道(FIFO)则作为一种特殊的文件存在于文件系统中,允许不同进程通过命名进行通信,具有更广泛的应用场景。 文章详细解释了...

    java进程间管道通信1

    Java进程间的管道通信是一种进程间通信(IPC,Inter-Process Communication)的方式,它允许不同的Java进程之间通过共享的管道进行数据传输。...通过理解这些概念和注意事项,开发者可以构建出可靠的多进程通信系统。

    进程间软中断通信和管道通信

    管道是一种半双工的通信方式,数据只能单向流动,且具有先进先出(FIFO)的特点。在两个进程之间创建一个管道,可以使得一个进程的数据被另一个进程读取。在Linux中,可以使用`pipe()`函数创建管道,然后通过`fork()...

Global site tag (gtag.js) - Google Analytics