《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; }
结束
学会了管道的一些简单应用。