HOME

《Unix/Linux编程实践教程》笔记(9)──IO重定向和管道

Table of Contents

内容

Unix 默认规定程序从文件描述符0读取数据,写数据到文件描述符1,将错误信息输处到文件描述符2.这三个文件描述符称为标准输入,输出及标准错误输出。

创建系统描述符的系统调用总是使用最低可用文件描述符号。也就是说,你关闭文件描述符0,再创建一个文件描述符,返回的是0。

管道是内核中的一个数据队列,每端连接一个文件描述符。可以通过调用pipe系统调用创建管道。

fork后,父进程中的管道也会复制给子进程。

复制文件描述符 newfd=dup(oldfd)
复制文件描述符 dup2(oldfd,newfd)
创建管道 pipe(int array[ 2 ])

习题

10.1

shell使用的是自动添加模式。

10.2

交换父进程和子进程后,父进程产生完数据就马上结束了,子进程接收到管道中的数据并且处理,然后一直等待管道写入端被关闭,挂起。

10.4

父进程中没有关闭写入端,然后执行sort命令,没有接收到数据。接着子进程产生数据,然而父进程没再从管道读取数据,程序没有输出。

10.8

父进程先堵塞,等待子进程数据被写入管道,子进程写完关闭管道退出,父进程读取到数据后也关闭退出程序。不需要用wait等待子进程返回。

10.10

没有实现第三项

#!/bin/bash
trap "rm -f {prev.*,curr.*};exit"  2 3 15

prev=`mktemp prev.XXXXXX`
curr=`mktemp curr.XXXXXX`

list=()
while  read line;do
	if [ -z "$line" ];then
		continue;
	fi
	if [ -z "$list" ];then
		list=("$line")
	else
		list=("${list[@]}"' '"$line") ##用空格分开
	fi

	##echo $line
done < $1
##echo $list
for i in $list
do
	echo $i
done

for i in $list
do
	who | grep $i  >> $prev
done
sort $prev -o $prev
while true;do
	sleep 60
	for i in $list
	do
		who | grep $i  >> $curr
	done
	sort $curr -o $curr
	res=`comm -23 $prev $curr`
	if [ -n "$res" ];then
		echo "logged out:"
		echo $res
	fi
	res=`comm -13 $prev $curr`
	if [ -n "$res" ];then
		echo "logged in:"
		echo $res
	fi
	mv $curr $prev
done

10.11

open的flag加一个O_APPEND

10.13

写的有些混乱

#include	<stdio.h>

/**
 *	pipe.c		* Demonstrates how to create a pipeline from
 *			  one process to another
 *
 *			* Takes two args, each a command, and connects
 *			  av[1]'s output to input of av[2]
 *			* usage: pipe command1 command2
 *			  effect: command1 | command2
 *			* Limitations: commands do not take arguments
 *			* uses execlp() since known number of args
 *			* Note: exchange child and parent and watch fun
 **/

main(ac, av)
char **av;
{
	int	thepipe[2],			/* two file descriptors	*/
		newfd,				/* useful for pipes	*/
		pid;				/* and the pid		*/

	if ( ac != 4 ){
		fprintf(stderr, "usage: pipe cmd1 cmd2\n");
		exit(1);
	}
	if ( pipe( thepipe ) == -1 ){		/* get a pipe		*/
		perror( "cannot create pipe" );
		exit(1);			/* or exit		*/
	}

	/* ------------------------------------------------------------ */
	/*	now we have a pipe, now let's get two processes		*/

	if ( (pid = fork()) == -1 ){			/* get a proc	*/
		fprintf(stderr,"cannot fork\n");
		exit(1);				/* or exit	*/
	}

	/* ------------------------------------------------------------ */
	/* 	Right Here, there are two processes			*/
	/*
	 *	parent will read from reading end of pipe
	 */

	if ( pid > 0 ){			/* the child will be av[2]	*/
		close(thepipe[1]);	/* close writing end		*/
		close(0);		/* will read from pipe		*/
		newfd=dup(thepipe[0]);	/* so duplicate the reading end	*/
		if ( newfd != 0 ){	/* if not the new stdin..	*/
			fprintf(stderr,"Dupe failed on reading end\n");
			exit(1);
		}
		close(thepipe[0]);	/* stdin is duped, close pipe	*/
		execlp( av[3], av[3], NULL);
		exit(1);		/* oops				*/
	}

	/*
	 *	child will write into writing end of pipe
	 */
	close(thepipe[0]);	/* close reading end		*/
	close(1);		/* will write into pipe		*/
	newfd=dup(thepipe[1]);	/* so duplicate writing end	*/
	if ( newfd != 1 ){	/* if not the new stdout..	*/
		fprintf(stderr,"Dupe failed on writing end\n");
		exit(1);
	}
	close(thepipe[1]);	/* stdout is duped, close pipe	*/

	if ( pipe( thepipe ) == -1 ){		/* get a pipe		*/
		perror( "cannot create pipe" );
		exit(1);			/* or exit		*/
	}
	if ( (pid = fork()) == -1 ){			/* get a proc	*/
		fprintf(stderr,"cannot fork\n");
		exit(1);				/* or exit	*/
	}
	if (pid > 0){
		close(thepipe[1]);
		close(0);
		newfd=dup(thepipe[0]);
		if (newfd != 0){
			fprintf(stderr,"Dup failed on writing end\n");
			exit(1);
		}
		execlp( av[2], av[2], NULL);
		exit(1);		/* oops				*/
	}
	close(thepipe[0]);
	close(1);
	newfd=dup(thepipe[1]);
	if (newfd != 1){
		fprintf(stderr,"Dup failed on writing end\n");
		exit(1);
	}
	execlp(av[1], av[1], NULL);
	exit(1);

	}

10.14

没有想到解决法方法

10.15

从标准输入读一次,分别写入到标准输出和文件。

#include	<stdio.h>


int main(int ac, char *av[])
{
	int	thepipe[2],			/* two file descriptors	*/
		newfd,				/* useful for pipes	*/
		pid;				/* and the pid		*/
	FILE *fp;
	char buf[64];
	int len;

	if ( ac != 2 ){
		fprintf(stderr, "usage: pipe cmd1 cmd2\n");
		exit(1);
	}
	if ( pipe( thepipe ) == -1 ){		/* get a pipe		*/
		perror( "cannot create pipe" );
		exit(1);			/* or exit		*/
	}
	fp = fopen(av[1], "w");

	while((len = read(0, buf, 64)) > 0){
		buf[len]='\0';
		fprintf(stdout, "%s", buf);
		fprintf(fp, "%s", buf);
	}


	return 0;

}

10.16

就是前面章节的内容啊

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

int main (void){
	int fd;
	struct stat buf;

	fd = open("aaa", O_RDWR);

	fstat(fd, &buf);

	if (S_ISREG(buf.st_mode))
		printf("is regular file\n");
	


	return 0;
}

结束

学会了管道的一些简单应用。

Created: 2018-09-26 Wed 18:52

Emacs 24.5.1 (Org mode 8.2.10)