读书笔记:第4章 管道和FIFO (2)

        《UNIX网络编程:卷2》P38 图4-14 测试全双工管道的双向通信能力

/*P38 fduplex.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main(int argc, char *argv[])
{
	int		fd[2], n;
	char	c;
	pid_t	childpid;

	// 创建管道
	if (pipe(fd) < 0) {
		fprintf(stderr, "pipe error: %s\n", strerror(errno));
		exit(1);
	}

	// 创建一个新进程
	if ((childpid = fork()) < 0) {
		fprintf(stderr, "fork error: %s\n", strerror(errno));
		exit(1);
	} else if (childpid == 0) {
		// 子进程
		sleep(3);

		// 通过0从管道中读取数据
		if ((n = read(fd[0], &c, 1)) != 1) {
			if (n < 0)
				fprintf(stderr, "read error: %s\n", strerror(errno));
			fprintf(stderr, "child: read returned %d\n", n);
			exit(1);
		}
		printf("child read %c\n", c);

		// 通过0向管道中写入数据
		if (write(fd[0], "c", 1) != 1) {
			fprintf(stderr, "write error: %s\n", strerror(errno));
			exit(1);
		}
		exit(0);
	}
	// 父进程

	// 通过1向管道中写入数据
	if (write(fd[1], "p", 1) != 1){
		fprintf(stderr, "write error:%s\n", strerror(errno));
		exit(1);
	}

	// 通过1从管道中读取数据
	if ((n = read(fd[1], &c, 1)) != 1) {
		fprintf(stderr, "read error: %s\n", strerror(errno));
		fprintf(stderr, "parent: read returned %d\n", n);
		exit(1);
	}

	printf("parent read %c\n", c);
	exit(0);
}

        这儿的全双工管道是由两个半双工管道构成的。写入fd[1]的数据只能从fd[0]读出,写入fd[0]的数据只能从fd[1]读出。

        我们创建一个全双工管道然后调用fork,父进程写入字符p,然后从中读出一个字符。子进程先睡眠3秒,从该管道读出一个字符后,往它写入字符c。子进程睡眠是为了让父进程的read调用先于子进程的read执行,从而看出父进程是否读回自己刚写的字符。

        在Ubuntu14.04中运行:

$ ./fduplex 
read error: Bad file descriptor
parent: read returned -1
$ child read p
write error: Bad file descriptor

        父进程写入字符p,它由子进程读出,但此后父进程在试图从fd[1]read时中止,子进程则试图往fd[0]write时中止。

        由此可见,Linux默认提供的是半双工管道(编译时指定不同的选项,能否提供全双工管道?)。

你可能感兴趣的:(读书笔记,《UNIX网络编程》)