Linux编程练习 --进程间通信1--无名管道

进程间通信系列--管道

管道可以说是最古老的IPC形式,所谓管道,是指进程间建立的一条通信的通道,从本质上看,管道是UNIX文件概念的推广管道通信的介质是文件,先看一下管道的特点:

 

1.管道的特点:

  (1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

  (2)无名管道只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);后来发展了FIFO(也称有名管道)

  (3)单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。

   (4)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

 

2.无名管道API及操作:

头文件:#include <unistd.h>

数据成员:int pipe_fd[2];

管道创建:int pipe(int fd[2])

    该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。

管道读写:

管道两端可分别用描述字fd[0]以及fd[1]来描述,管道读端:fd[0],管道写端:fd[1];

读管道规则:

 关闭管道的写端:close (fd[WRITE]);

读出:read(fd[READ],string,strlen(string));

读出后关闭管道的读端:close(fd[REAd]);

 

写管道规则:

关闭管道的读端:close(fd[REAd]);

写入:write(fd[WRITE],string,strlen(string));

写入后关闭管道的写端:close (fd[WRITE]);

 

下面练习一个简单的单管道通信:

父进程写数据,子进程负责读出数据

 

[cpp]  view plain copy
  1. /**************  
  2.   * readtest.c *  
  3.    
  4. **************/   
  5. #include <unistd.h>   
  6. #include <sys/types.h>   
  7. #include <errno.h>   
  8. #define     READ    0  
  9. #define     WRITE   1  
  10. main()   
  11. {     
  12.     int pipe_fd[2];       
  13.     pid_t pid;    
  14.     char r_buf[100];      
  15.     char w_buf[32];       
  16.     char* p_wbuf;   
  17.     int r_num;    
  18.     int cmd;      
  19.     memset(r_buf,0,sizeof(r_buf));    
  20.     memset(w_buf,0,sizeof(r_buf));    
  21.     p_wbuf=w_buf;     
  22.     if(pipe(pipe_fd)<0)        
  23.     {         
  24.         printf("pipe create error ");         
  25.         return -1;        
  26.     }   
  27.       
  28.     if((pid=fork())==0) //子进程读        
  29.     {     
  30.         close(pipe_fd[WRITE]);    
  31.         sleep(3);           //确保父进程关闭写端   
  32.         r_num=read(pipe_fd[READ],r_buf,100);   
  33.         printf( "read num is %d the data read from the pipe is %s /n",r_num,r_buf);       
  34.         close(pipe_fd[READ]);     
  35.         exit();           
  36.     }     
  37.     else if(pid>0)   //父进程写  
  38.     {         
  39.         close(pipe_fd[READ]);         
  40.         strcpy(w_buf,"hello world!/n");           
  41.         if(write(pipe_fd[WRITE],w_buf,strlen(w_buf))==-1)         
  42.             printf("parent write over/n ");           
  43.         close(pipe_fd[WRITE]);        
  44.         printf("parent close fd[WRITE] over /n");         
  45.         sleep(10);   
  46.     }     
  47. }   

编译运行,看到预期结果

 

3.利用两个管道进行双向通信

(1)创建两个管道:管道1(父->子),管道2(子->父)

(2)fork()产生子进程

(3)父进程:close(fd1[READ]); close(fd2[WRITE]);

(4)子进程:close(fd1[WRITE]); close(fd2[READ]);

下面做一个练习,是利用双向通信实现父子进程协作把整数x从1加到10

[cpp]  view plain copy
  1. #include <unistd.h>  
  2. #include <sys/stat.h>  
  3. #include <sys/types.h>  
  4. #include <stdio.h>  
  5. #include <fcntl.h>  
  6. #define MAXLINE 1024  
  7. #define READ    0  
  8. #define WRITE   1  
  9. main(void)  
  10. {  
  11.     int x;  
  12.     pid_t pid;  
  13.     int pipe1[2],pipe2[2];  
  14.     /*初始化管道*/  
  15.     pipe(pipe1);  
  16.     pipe(pipe2);  
  17.     pid = fork();  
  18.     if(pid < 0)  
  19.     {  
  20.         printf("create process error!/n");  
  21.         exit(1);  
  22.     }  
  23.     if(pid == 0)        //子进程  
  24.     {  
  25.         close(pipe1[WRITE]);  
  26.         close(pipe2[READ]);  
  27.         do  
  28.         {  
  29.             read(pipe1[READ],&x,sizeof(int));  
  30.             printf("child %d read: %d/n",getpid(),x++);  
  31.             write(pipe2[WRITE],&x,sizeof(int));  
  32.         }while(x<=9);  
  33.         //读写完成后,关闭管道  
  34.         close(pipe1[READ]);  
  35.         close(pipe2[WRITE]);  
  36.         exit(0);  
  37.     }  
  38.     else if(pid > 0) //父进程  
  39.     {  
  40.         close(pipe2[WRITE]);  
  41.         close(pipe1[READ]);  
  42.         x = 1;  
  43.         //每次循环向管道1 的1 端写入变量X 的值,并从  
  44.         //管道2 的0 端读一整数写入X 再对X 加1,直到X 大于10  
  45.         do{  
  46.             write(pipe1[WRITE],&x,sizeof(int));  
  47.             read(pipe2[READ],&x,sizeof(int));  
  48.             printf("parent %d read: %d/n",getpid(),x++);  
  49.         }while(x<=9);  
  50.         //读写完成后,关闭管道  
  51.         close(pipe1[WRITE]);  
  52.         close(pipe2[READ]);  
  53.         waitpid(pid,NULL,0);  
  54.         exit(0);  
  55.     }  
  56. }  

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 无名管道(Anonymous Pipe)是操作系统中用于实现进程间通信(IPC)的一种机制,Windows操作系统也支持使用无名管道进行进程间通信。 在Windows操作系统中,无名管道是一种特殊类型的文件,只能用于相关进程间通信,无法用于不相关进程间通信无名管道通常是单向的,有一个读取端(Read end)和一个写入端(Write end),一个进程可以往管道的写入端写入数据,另一个进程可以从管道的读取端读取数据。 无名管道常用于兄弟进程间通信(如父子进程)或者由同一个进程创建的两个进程间通信。 使用无名管道进行进程间通信的步骤如下: 1. 创建管道:调用CreatePipe函数创建一个无名管道,返回读取端和写入端句柄。 2. 创建进程:使用CreateProcess函数创建需要进行通信的进程。 3. 设置进程的标准输入输出:使用SetStdHandle函数将管道的读取端和写入端句柄分别设置为所创建进程的标准输入和标准输出。 4. 进程通信:通过写入端句柄向管道写入数据,然后通过读取端句柄从管道读取数据。 在这个过程中,写入端和读取端可以位于同一个进程中,也可以位于不同的进程中。写入端写入的数据会被读取端读取,实现了进程间的通信。 无名管道可以用于传输任意类型的数据,包括文本、二进制等。只要进程通过读取端和写入端的兼容接口进行数据的读写操作,就可以实现进程间的通信。 总之,使用无名管道是一种简单有效的方式来实现Windows操作系统中进程间的通信,通过读取端和写入端的数据传输,可以实现数据的共享和交换,满足进程间通信的需求。 ### 回答2: 无名管道(Anonymous Pipes)是一种在Windows系统中用于实现进程间通信的机制。它通常用于在父子进程之间或者兄弟进程之间进行数据传输。 在使用无名管道之前,我们需要创建一个匿名的管道对象,它定义了一个读取端和一个写入端。父进程可以通过创建管道对象,并将写入端传递给子进程,来实现进程间通信。子进程可以通过读取从父进程写入端传来的数据来获取信息。 无名管道的使用步骤如下: 1. 使用CreatePipe函数创建一个无名管道,该函数返回两个句柄(一个读句柄和一个写句柄),分别用于读取和写入管道中的数据。 2. 通常,我们会在父进程中调用CreateProcess函数创建一个子进程。子进程会继承父进程的句柄。 3. 在创建子进程后,父进程可以关闭子进程中不需要的句柄(写句柄),子进程可以关闭父进程中不需要的句柄(读句柄)。 4. 当父进程想要向子进程发送数据时,它可以使用WriteFile函数来向写入端写入数据。 5. 子进程可以使用ReadFile函数从读取端读取父进程写入的数据。 通过这种方式,父进程和子进程之间可以进行双向的通信。 需要注意的是,无名管道只适用于具有亲密关系(比如父子进程)或具有共同祖先(比如兄弟进程)的进程之间。此外,无名管道是半双工的,意味着只能在一个方向上传递数据。如果需要实现双向通信,可以使用两个无名管道来分别实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值