Linux编程基础之进程间通信之二:有名管道

一、有名管道的简单说明

无名管道只能在具有亲缘关系的进程间通信,大大地限制了管道的使用。而有名管道的出现则突破了这种限制,它可以使任意两个进程间进行通信。该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。。不过值得注意的是,FIFO 是严格地遵循先进先出规则的,对管道及FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如lseek()等文件定位操作。

有名管道的创建可以使用函数mkfifo(),该函数类似文件中的open()操作,可以指定管道的路径和打开的模式。在创建管道成功之后,就可以使用open()、read()和write()这些函数了。与普通文件的开发设置一样,对于为读而打开的管道可在open()中设置O_RDONLY,对于为写而打开的管道可在open()中设置O_WRONLY,在这里与普通文件不同的是阻塞问题。由于普通文件的读写时不会出现阻塞问题,而在管道的读写中却有阻塞的可能,这里的非阻塞标志可以在open()函数中设定为O_NONBLOCK。下面分别对阻塞打开和非阻塞打开的读写进行讨论。

(1)对于读进程

  • 若该管道是阻塞打开,且当前FIFO 内没有数据,则对读进程而言将一直阻塞到有数据写入。
  • 若该管道是非阻塞打开,则不论FIFO 内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0。
(2)对于写进程

  • 若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。
  • 若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。

二、有名管道的创建函数

管道创建函数如下所示:

int mkfifo(const char *filename,mode_t mode)
        filename:要创建的管道

        mode :  O_RDONLY,读管道

                      O_WRONLY,写管道
                      O_RDWR,读写管道

                      O_NONBLOCK:非阻塞

                      O_CREAT:如果该文件不存在,那么就创建一个新的文件,并用第三个参数为其设置权限

                      O_EXCL:如果使用O_CREAT 时文件存在,那么可返回错误消息。这一参数可测试文件是否存在

        返回值:0成功,其他返回错误代码

操作中经常会出现以下错误如下表所示(方便出错查询):



三、测试

编写一个实例进行测试:需要编写两个独立进程,一个进程用来读取传入的数据,一个进程用来写入数据;在读进程当中首先创建的fifo文件,然后打开并不停的读取FIFO文件当中的内容,在写进程当中打开FIFO文件然后向FIFO文件当中写入相应的内容。具体如下:

读端:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define FIFO_NAME		"yl_fifo"	// 定义FIFO文件的名称
#define BUFFER_SIZE		256			// 定义缓冲区的大小

/*	创建FIFO文件,并以阻塞方式读取FIFO文件当中的内容
 *
 */
int main(void)
{
	int ret;

	int fd;
	char buf[BUFFER_SIZE];
	int buflen;

	/* 创建FIFO文件 */
	if(-1 == access(FIFO_NAME, F_OK))	// 判断FIFO文件是否存在
	{
		ret = mkfifo(FIFO_NAME, 0666);  // 以可读可写方式创建一个FIFO文件
		if(-1 == ret)
		{
			printf("mkfifo error!\n");
			return -1;
		}
	}

	fd = open(FIFO_NAME, O_RDONLY);		// 打开这个文件
	if(-1 == fd)
	{
		printf("open error!\n");
		return -1;
	}

	/* 以阻塞的方式读取文件当中的内容 */
	while(1)
	{
		memset(buf, 0, BUFFER_SIZE);
		buflen = read(fd, buf, BUFFER_SIZE);
		if(buflen > 0)
		{
			buf[buflen] = '\0';
			if(!strcmp("quit", buf))	// 如果读到的信息是quit,则退出
			{
				return 0;
			}
			else	// 将读取的信息打印出来
			{
				printf("Read from fifo : %s\n", buf);
			}	
		}
	}
	
	close(fd);	// 关闭这个文件
	
	return 0;
}

写端:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define FIFO_NAME		"yl_fifo"	// 定义FIFO文件的名称
#define BUFFER_SIZE		256			// 定义缓冲区的大小

/*	向FIFO文件当中写入信息
 *		usage : fifo_write <info>
 */
int main(int argc, char *argv[])
{
	int fd;

	char buf[BUFFER_SIZE];
	int buflen;

	if(2 != argc)
	{
		printf("usage : %s <info>\n", argv[0]);
		return -1;
	}

	fd = open(FIFO_NAME, O_WRONLY);		// 打开这个文件
	if(-1 == fd)
	{
		printf("open error!\n");
		return -1;
	}

	/* 将消息写入FIFO文件当中 */
	sprintf(buf, "%s", argv[1]);
	buflen = write(fd, buf, BUFFER_SIZE);
	if(buflen <= 0)
	{
		printf("write error!\n");
		return -1;
	}
	else
	{
		printf("Write to fifo : %s\n", buf);
	}

	close(fd);		// 关闭这个文件

	return 0;
}
对读端和写端分别进行编译和运行如下所示:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值