信息安全设计基础第十周学习总结
10.7 I/O重定向
unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出连接起来。例如:
ls > foo.txt
使得外壳加载和执行ls程序,将标准输出重定向到foo.txt。
I/O重定向的工作方式:
使用dup2函数:
#include <unistd.h>
int dup2(int oldfd,int newfd);
dup2函数拷贝描述符表项oldfd到描述符表项newfd,同时覆盖掉newfd之前的内容。如果newfd已经打开,dup2会在拷贝oldfd之前先关闭newfd。
例:调用dup2(4,1)之前,描述符1对应文件A,描述符对应文件B,A和B的引用计数都是1
调用dup2(4,1)后,两个描述符都指向文件B,文件A被关闭,文件表和v-node表也被删除了,文件B的引用计数已经增加了,从此以后,任何写到标准输出的数据都被重定向到文件B。
练习题10.4 如何使用dup2将标准输入重定向到描述符5?
重定向标准输入(描述符0)到描述符5,可以调用dup2(5,0)进行重定向。
练习题10.5 假设磁盘文件foo.txt由6个ASCII码字符“foobar”组成,那么下列程序的输出是什么?
#include "csapp.h"
int main()
{
int fd1,fd2;
char c;
fd1 = Open("foobar.txt",O_RDONLY,0);
fd2 = Open("foobar.txt",0_RDONLY,0);
Read(fd2,&c,1);
Dup(fd2,fd1);
Read(fd1,&c,1);
printf("c= %c\n",c);
exit(0);
}
fd1被重定向到了fd2,所以输出的是第二个字母o
10.8 标准I/O
标准I/O库(libc)提供了打开和关闭文件的函数(fopen和fclose)、读和写字节的函数(fread和fwrite)、读和写字符串的函数(fgets和fputs),以及复杂的格式化的I/O函数(scanf和printf)
标准I/O库将一个打开的文件模型化为一个流。一个流就是一个指向FILE类型的结构的指针,每个ANSI C程序开始时都有三个打开的流:stdin,stdout,stderr,分别对应于标准输入,标准输出,标准错误。
类型为FILE的流是对文件描述符和流缓冲区的抽象,流缓冲区的目的是使开销较高的Unix I/O系统调用的数量尽可能的小。
附录A 错误处理
1.Unix风格的错误处理
返回值既包括错误代码也包括有用的结果
2.Posix风格的错误处理
只用返回值表示成功(0)或者失败(非0)。任何有用的结果都返回在通过引用传递进来的函数参数中。
3.DNS风格的错误处理
失败时返回NULL指针,并设置全局变量h_errno
4.错误报告代码
Unix风格:
void unix_error(char *msg)
{
fprintf(stderr,"%s: %s\n",msg,strerror(errno));
exit(0);
}
Posix风格:
void posix_error(int code, char *msg)
{
fprintf(stderr,"%s:%s\n",msg,strerror(code));
exit(0);
}
DNS风格:
void dns_error(char *msg)
{
fprintf(stderr,"%s:DNS error %d\n",msg,h_errno);
exit(0);
}
5.错误处理包装函数
unix风格
void Kill(pid_t pid, int signum)
{
int rc;
if((rc = kill(pid,signum))<0);
unix_error("Kill error");
}
Posix风格
void Pthread_detach(pthread_t tid)
{
int rc;
if(rc=pthread_detach(tid)!=0
posix_error(rc,"Pthread_death error");
}
DNS风格
struct hostent *Gethostbyname(const char *name)
{
struct hostname *p;
if((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
参考资料
教材