> 文章列表 > <Linux开发> linux应用开发-之-进程通信之管道例程

<Linux开发> linux应用开发-之-进程通信之管道例程

<Linux开发> linux应用开发-之-进程通信之管道例程

一、简介

所谓管道,是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称 pipe 文件。

向管道(共享文件)提供输入的发送进程(即写进程),以字符流形式将大量的数据送入管道;而接收管道输出的接收进程(即读进程),可从管道中接收数据。由于发送进程和接收进程是利用管道进行通信的,故又称管道通信。

为了协调双方的通信,管道通信机制必须提供以下3 方面的协调能力。

(1)互斥。当一个进程正在对 pipe 进行读/写操作时,另一个进程必须等待。
(2)同步。当写(输入)进程把一定数量(如4KB)数据写入 pipe 后,便去睡眠等待,直到读(输出)进程取走数据后,再把它唤醒。当读进程读到一空 pipe 时,也应睡眠等待,直至写进程将数据写入管道后,才将它唤醒。
(3)对方是否存在。只有确定对方已存在时,才能进行通信。

二、环境搭建

本次测试pipe通信的应用例程是运行在ubuntu pc上的;当然也是可以运行在linux开发板 或相关linux设备上的。
开发环境无特别要求。

三、例程代码

本次代码会使用单独的一个c文件用来pipe进程代码,使用子进程写入数据到Pipe中,并通过主进程读取pipe中的数据并打印。
创建.c文件,并输入一下内容:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>#define INPUT 1
#define OUTPUT 0void main()
{int Upipe[2];                   //用以管道描述符pid_t pid;                      //用于子进程pid创建char buf[256];                  //用于存放接收管道的数据int returned_count;             //读取管道的返回值状态int i =0;                       //计数用char Sendbuf[256];              //用于存放发送管道的数据/*创建无名管道*///pipe(Upipe);if (pipe(Upipe) == -1) {        //创建管道perror("pipe");             //终端输出exit(EXIT_FAILURE);         //退出}/*创建子进程*/if((pid = fork()) == -1){       //创建子进程printf("Error in fork\\n");  //终端输出exit(1);                    //退出}if(pid == 0) {while(1){   /*子进程运行内容*/printf("in the spawned child process ... \\n");sprintf(Sendbuf,"TEST data:%d \\n",i);               //组合需要发送的数据内容if(i%2)                                             //计数值对2取余数{close(Upipe[OUTPUT]);                            //管壁输入write(Upipe[INPUT],Sendbuf, strlen(Sendbuf));}i++;if(i>100000){i=0;}sleep(1);}} else {while(1){ /*主进程运行内容*/printf("in the spawned parent process ... \\n");close(Upipe[INPUT]);returned_count = read(Upipe[OUTPUT],buf, sizeof(buf));printf("%d bytes of data received from spawned prcess :%s \\n",returned_count, buf);sleep(1);}}}

四、编译运行

1、编译命令:

gcc  -g -o UnnamedPipes  UnnamedPipes.c

2、运行命令

./UnnamedPipes

3、运行输出效果如下图:
<Linux开发> linux应用开发-之-进程通信之管道例程

五、总结

管道写操作流程如下:
写之前先锁定内存。
获取可写的缓冲区,若可写则循环写。
若不可写,则唤醒读进程,同时写进程进行休眠,让出 CPU。

读的操作很简单,操作如下:
读之前先锁定内存。
从缓冲区中获取数据页,把页中数据拷贝到用户缓冲区中。
数据全部被读完,则发送信号唤醒写进程,同时读进程让出 CPU 进行休眠。

管道也称无名管道,是 UNIX 系统中进程间通信(IPC)中的一种。
管道由于是无名管道,因此只能在有亲缘关系的进程间使用。
管道不是普通的文件,它是基于内存的。
管道属于半双工,数据只能从一方流向另一方,也即数据只能从一端写,从另一端读。
管道中读数据是一次性的操作,数据读取后就会释放空间,让出空间供更多的数据写。
管道写数据遵循先入先出的原则。

注意,在这个例子中,为什么这两个进程都关闭它所不需的管道端呢?

这是因为写进程完全关闭管道端时,文件结束的条件被正确地传递给读进程。而读进程完全关闭管道端时,写进程无需等待继续写数据。

阻塞读和写分别成为对空和满管道的默认操作,这些默认操作也可以改变,这就需要调用 fcntl() 系统调用,对管道文件描述符设置 O_NONBLOCK 标志可以忽略默认操作:

#include <fcntl.h>fcntl(fd,F_SETFL,O_NONBlOCK);

管道作为进程通信的一种方法,在实际开发中也是经常会使用的。上述例程是一个简单的运用例子。读者自行参考学习使用。
欢迎交流…