1.三个数据流
标准输入:需要处理得数据流。标准文件描述符:0--stdin
标准输出:结果数据流。标准文件描述符:1--stdout
标准错误输出:错误信息流。标准文件描述符:2--stderr
2.重定向I/O的是shell而不是程序
cmd>filename告诉shell将文件描述符1定位到文件。于是shell就将文件描述符与指定的文件连接起来。
shell并不将重定向标记和文件名传递给程序。
实例证明:
#include<stdio.h>
main(int argc,char *argv[]){
int i;
printf("%d args:\n",argc);
for(i=0;i<argc;i++){
printf("%s\n",argv[i]);
}
fprintf(stderr,"this is message sent to stderr.\n");
}
结果分析:
$ ./listargs testing >xyz one two 2> oops
只有testing、one、two是命令的参数,>xyz和2>oops是用来作重定向的,且testing、one、two和>xyz、2>oops的位置可以任意的交换都不影响结果。
stdout上没有输出,输出全部到了xyz和oops两个文件里:
$ cat xyz
4 args:
./listargs
testing
one
two
$ cat oops
this message is sent to stderr.
shell提供文件描述符2的重定向。
shell的重定向操作:
一 .who>userlist 将stdout文件连接到一个文件
二 .sort<data 将stdin连接到一个文件
三.who | sort 将stdout连接到stdin
3.”最低可用文件描述符“原则
”最低可用文件描述符“原则:当打开文件时,为此文件安排的描述符总是此数组中最低可用位置的索引。
因此将stdin定向到文件实现起来其实非常简单:先close(0),再打开一个文件,这时分配给该文件的文件描述符就是0。在读写文件时我们依然使用stdin(数字0)这个文件描述符,实现是在操作一上普通文件,而非标准输入。
实例:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<fcntl.h> 4 #include<string.h> 5 main(){ 6 int fd; 7 char line[100]; 8 fgets(line,100,stdin); 9 printf("%s",line); 10 close(0); 11 fd=open("/etc/passwd",O_RDONLY); 12 if(fd!=0){ 13 fprintf(stderr,"Could not open data as fd 0\n"); 14 exit(1); 15 } 16 fgets(line,100,stdin); 17 printf("%s",line); 18 }
结果以及分析:
$ gcc stdinredir1.c -o stdinredir1
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
main(){
int pid;
int fd;
printf("About to run who into a file\n");
if((pid=fork())==-1){ //创建子进程
perror("perror");
exit(1);
}
if(pid==0){ //在子进程中
close(1); //关闭文件描述符1
fd=creat("userlist",0644); //创建一个新文件,此时它获得文件描述任1
execlp("who","who",NULL); //如果本句执行成功,下面的代码就不会执行
perror("execlp");
exit(1);
}
if(pid!=0){ //在父进程中等待子进程退出
wait(NULL); //等待某个子进程退出
printf("Done running who.results in userlist\n");
}
}
结果及分析:
orisun tty7 2011-12-24 14:21 (:0)
orisun pts/1 2011-12-24 14:44 (:0.0)
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
main(){
int fd;
int newfd;
char line[100];
fgets(line,100,stdin);
printf("%s",line);
fd=open("/etc/passwd",O_RDONLY);
newfd=dup2(fd,0); //将标准输入重定向到文件
if(newfd!=0){
fprintf(stderr,"Could not duplicate fd 0\n");
exit(1);
}
close(fd);
fgets(line,100,stdin);
printf("%s",line);
}
结果与分析:
4.I/O重定向是如何工作的?
首先,unix进程使用文件描述符0,1,2作为标准输入、输出和错误的通道。
其次,当进程请求一个新的描述符的时候,系统内核将最低可用的文件描述符复制给他。具体如何复制参考上面例子。
5.I/O重定向的基本概念
a、 I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9;
b、 常用FD有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),默认与keyboard、monitor有关;
6.基本的I/O
7.进阶的I/O