linux 进程间通信编程,管道通信的实验

代码分析

  程序分析

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>	//mkfifo
#include <sys/stat.h>	//mkfifo

// 定义FIFO有名管道名
#define FIFO1	"in1"			
#define FIFO2	"in2"
//设定缓冲区大小
#define BUF_SIZE	512
//超时时间
#define DELAY_TIME	60
//多路复用文件数目
#define IN_FILES	3
#define MAX(a,b)	((a) > (b)? (a) : (b))

int main()
{
	int fds[IN_FILES];
	char buf[BUF_SIZE];
	int i, res, real_read, maxfd;
	fd_set inset, tmpset;
	struct timeval tv;	//超时时间设置

	fds[0] = 0;			//标准输入设备

	//创建两个有名管道
	//access - check real user's permissions for a file
	//#include <unistd.h>
	//int access(const char *pathname, int mode);
	//mode: F_OK, R_OK, W_OK, and X_OK.
	//mkfifo - make a FIFO special file (a named pipe)
	//#include <sys/types.h>
	//#include <sys/stat.h>
	//int mkfifo(const char *pathname, mode_t mode);
	
	if((access(FIFO1, F_OK)) == -1)		//如果 FIFO1 有名管道不存在
	{
		if((mkfifo(FIFO1, 0666)) == -1)
		{
			perror("Error FIFO1 create!");
			exit(-1);
		}
	}
	
	if((access(FIFO2, F_OK)) == -1)		//如果 FIFO2 有名管道不存在
	{
		if((mkfifo(FIFO2, 0666)) == -1)//指明创建一个有名管道且存取权限为0666,即创建者、与创建者同组的用户、其他用户对该有名管道的  访问权限 都是 可读可写。
		{
			perror("Error FIFO2 create!");
			exit(-1);
		}
	}

	//以只读非阻塞的方式打开两个文件
	
	if((fds[1] = open(FIFO1, O_RDONLY|O_NONBLOCK)) == -1)
	{
		perror("Error FIFO1 open");
		exit(-1);
	}
	
	if((fds[2] = open(FIFO2, O_RDONLY|O_NONBLOCK)) == -1)
	{
		perror("Error FIFO2 open");
		exit(-1);
	}

	//以下为select函数作准备
	//取出两个文件描述符中的较大者
	maxfd = MAX(fds[1], fds[2]);
	//初始化读集合inset
	FD_ZERO(&inset);
	//在读文件描述符中加入相应的描述符
	for(i = 0; i < IN_FILES; i++)
	{
		FD_SET(fds[i], &inset);
	}

	tv.tv_sec = DELAY_TIME;
	tv.tv_usec = 0;

	//使用select函数循环测试监测的读文件描述符集中是否有准备就绪的
	while(FD_ISSET(fds[0], &inset) || FD_ISSET(fds[1], &inset) || FD_ISSET(fds[2], &inset))
	{
		tv.tv_sec = DELAY_TIME;
		tv.tv_usec = 0;
		tmpset = inset;			//使用临时文件描述符集,避免每次初始化
		//int select(int nfds, fd_set *readfds, fd_set *writefds,
		//           fd_set *exceptfds, struct timeval *timeout);
		res = select(maxfd + 1, &tmpset, NULL, NULL, &tv);

		//根据函数返回值进行处理
		switch (res)
		{
			case -1:
			{
				perror("Error Select");
				exit(-1);
			}
			break;
			case 0:
			{
				printf("超时\n");
				return 1;
			}
			break;
			default:
			{
				for (i = 0; i < IN_FILES; i++)
				{
					if (FD_ISSET(fds[i], &tmpset))
					{
						memset(buf, 0, BUF_SIZE);
						real_read = read(fds[i], buf, BUF_SIZE);
						if (real_read == -1 )
						{
							if (errno != EAGAIN) 
							{
								return 1;
							}
						}		//  文件读出错处理
						else if(!real_read)
						{
							FD_CLR(fds[i], &inset);
							close(fds[i]);
						}		
						else	//	文件读正常处理
						{
							if (i == 0)
							{		// 标准终端输入处理(文件描述符是0)
								if ((buf[0] == 'q') || (buf[0] == 'Q'))
								{
									return 0;
								}
							}		
							else	// FIFO输入处理
							{
								buf[real_read] = '\0';
								printf("FIFO%d: %s", i, buf);
							}	//end if 输入处理
						}	//end if 文件处理 
					}	//end if 文件就绪处理
				}	//end for 文件轮询
			}
			break;
		}	//end switch

	}	//end while
	return 0;
}

执行结果

  同样没什么解释的,检测到in1,in2可读,就返回,在输入处理中打印到终端,检测到标准输入时,判断是否是“q/Q”,是则退出检测,超时后自动退出
执行结果