《Unix/Linux编程实践教程》笔记(9)──IO重定向和管道
内容
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;
}
结束
学会了管道的一些简单应用。