1

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

 3 years ago
source link: https://houye.xyz/2018-09/uup9/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

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

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

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

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

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

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

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

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

父进程先堵塞,等待子进程数据被写入管道,子进程写完关闭管道退出,父进程读取到数据后也关闭退出程序。不需要用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;
}

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK