Linux(八):进程通信IPC(二)之命名管道

       管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipe或FIFO)提出后,该限制得到了克服。 FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。值得注意的是, FIFO(first input first output)总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。


一、命名管道的创建与读写
Linux下有两种形式式创建命名管道。一是在Shell下交互地建立一个命名管道,二是在程序中使用系统函数建立命名管道。 Shell模式下可使用mknod或mkfifo命令。
函数原型如下:
#include <sys/types.h>
#include <sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);

int mkfifo(const char *path,mode_t mode);

“S_IFIFO|0666”指明创建⼀个命名管道且存取权限为0666,即创建者、与创建者同组的用户、其他用户对该命名管道的访问权限都是可读可写(这里要注意umask对生成的管道文件权限的影响) 。命名管道创建后就可以使用了,命名管道和管道的使用方法基本是相同的。只是使用命名管道时,必须先调用open()将其打开。因为命名管道是一个存在于硬盘上的文件,而管道是存在于内存中的特殊文件。需要注意的是,调用open()打开命名管道的进程可能会被阻塞。但如果同时用读写方式

(O_RDWR)打开,则一定不会导致阻塞;如果以只读方式(O_RDONLY)打开,则调用open()函数的进程将会被阻塞直到有写方打开管道;同样以写方式(O_WRONLY)打开也会阻塞直到有读方式打开管道。


三, 总结
        文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道。
命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和之前所讲的没有名字的管道(匿名管道)类似。
由于Linux中所有的事物都可被视为文件,所以对命名管道的使用也就变得与文件操作非常
的统一,也使它的使用非常方便,同时我们也可以像平常的文件名一样在命令中使用。


创建命名管道

这里我使用mkfifo:

server.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
int main()
{
	//printf("hello world\n");
	umask(0);
	if(mkfifo("./fifo",S_IFIFO|0666) < 0)
	{
		perror("mkfifo");
		return 1;
	}

	int fd = open("./fifo", O_RDONLY);
	if(fd < 0)
	{
		perror("open");
		return 2;
	}

	char buf[128];
	while(1)
	{
		ssize_t _s = read(fd, buf, sizeof(buf)-1);
		if(_s > 0)
		{
			buf[_s-1] = '\0';
			printf("client# %s\n",buf);
		}
		else if(_s == 0)
		{
			printf("client quit! I should quit!\n");
			break;
		}
		else
		{
			perror("read");
		}
	}

	close(fd);
	return 0;
}
client.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
int main()
{
	//printf("hello world\n");
//    umask(0);
//	if(mkfifo("./fifo",S_IFIFO|0666) < 0)
//	{
//		perror("mkfifo");
//		return 1;
//	}

	int fd = open("./fifo", O_WRONLY);
	if(fd < 0)
	{
		perror("open");
		return 2;
	}

	char buf[128];
	while(1)
	{
		printf("please enter# ");
		fflush(stdout);
		ssize_t _s = read(0, buf, sizeof(buf)-1);
		if(_s > 0)
		{
			buf[_s] = '\0';
			//printf("client# %s\n",buf);

			write(fd, buf, strlen(buf));
		}
		else if(_s == 0)
		{
			printf("client quit! I should quit!\n");
			break;
		}
		else
		{
			perror("read");
		}
	}

	close(fd);
	return 0;
}

运行结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值