日期:2014-05-16  浏览次数:20683 次

Linux下多任务间通信和同步-管道

Linux下多任务间通信-管道

嵌入式开发交流群280352802,欢迎加入!

1.管道简介

管道式Linux系统中最古老的进程间通信机制,这里所说的管道是指无名管道(PIPE),它可用于具有亲缘关系进程间的通信.有名管道(FIFO)克服了管道没有名字的限制,因此,除了具有管道所有具有的功能外,它还允许无亲缘关系进程间的通信.Linux的管道主要包括两种:无名管道和有名管道,本文主要介绍这两种管道.

把一个进程连接到另一个进程的一个数据流称为"管道".比如:ls|more.这条命令的作用是列出当前目录下的所有文件盒子目录,如果内容超过了一页则自动进行分页.符号"|"就是shell为ls和more命令简历的一条管道,它将ls的输出直接送进了more的输入.

无名管道特点
  • 它只能用于具有亲缘关系的进程之间的通信(也就是父子进程或者兄弟进程之间).
  • 它是一个半双工的通信模式,具有固定的读端和写端.
  • 管道也可以看成是一种特殊的文件,对于它的读写也可以使用普通的read(),write()等函数.但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中.
有名管道特点
  • 它可以使互不相关的两个进程实现彼此通信.
  • 该管道可以通过路径名来指出,并且在文件系统中是可见的.在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便.
  • FIFO严格地遵循先进先出规则,对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如lseek()等文件定位操作.

2.无名管道

2.1.管道创建和关闭

管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fds[0]和fds[1],其中fds[0]固定用于读管道,而fd[1]固定用于写管道,这样就构成了一个半双工的通道.管道关闭时只需将这两个文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符.
创建管道可以通过调用pipe()来实现.其语法如下:

由于得到的是文件描述符,一般文件的I/O函数都可以用于管道,如close,read,write等等.下面我们通过一个简单的例子来演示管道的I/O操作.
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
	static const char mesg[] = "Hello world!";	
	char buf[BUFSIZ];
	ssize_t rcount, wcount;
	int pipefd[2];
	size_t len;

    /*创建管道*/
	if (pipe(pipefd) < 0) {
		fprintf(stderr, "%s: pipe failed: %s\n", argv[0],
			strerror(errno));
		exit(1);
	}
	printf("PIPE: Read end = fd %d, write end = fd %d\n",
		pipefd[0], pipefd[1]);

    /*写管道*/
	len = strlen(mesg);
	if ((wcount = write(pipefd[1], mesg, len)) != len) {
		fprintf(stderr, "%s: write failed: %s\n", argv[0],
			strerror(errno));
		exit(1);
	}
	printf("Write <%s> via pipe\n", mesg);

    /*读管道*/
	if ((rcount = read(pipefd[0], buf, BUFSIZ)) != wcount) {
		fprintf(stderr, "%s: read failed: %s\n", argv[0],
			strerror(errno));
		exit(1);
	}

	buf[rcount] = '\0';
    /*添加字符串终止字符*/
	printf("Read <%s> from pipe\n", buf);

    /*关闭管道*/
	close(pipefd[0]);
	close(pipefd[1]);
	return 0;
}
程序的执行结果如下:
上面的这段程序没有什么有用的功能,只是演示了基本的概念.该程序所建立的管道如下图所示.需要注意的是:逛到的容量十分有限,在<limits.h>头文件中定义的常量PIPE_BUF规定的管道一次传送的最大字节数(4096).