信息安全设计基础第十周学习总结
信息安全设计基础第十周学习总结
【学习时间:8小时】 【学习内容:教材第十章 之 I/O总结;实验楼私有课程《深入理解计算机系统》 之 系统级I/O】
一、教材内容
1.I/O重定向
【重定向其实是unix系统优越性的一种体现(与管道相似);将一种操作的结果重定向到另外一种操作上,这样的思想保证了“专务专用”,将单个操作做到极致,又为用户自己提供了完善功能的平台(比如重定向,比如管道)。】 - unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出连接起来。例如:
ls > foo.txt;
使得外壳加载和执行ls程序,将标准输出重定向到foo.txt。
-
工作方式:
#include <unistd.h> int dup2(int oldfd,int newfd);
拷贝描述符表项oldfd到描述符表项newfd,同时覆盖掉newfd之前的内容。如果newfd已经打开,就先关闭newfd再进行操作。
- 调用dup2(4,1)示例:
前提:假设描述符1(标准输出)对应于文件A,4对应于文件B,A和B的引用计数等于1.
过程:两个描述符都指向文件B,文件A已经被关闭,它之前对应的文件表和v-node也已经被删 除;文件B的引用计数增加,之后的任何标准输出(描述符1)的数据都被重定向到文件B。
2.标准I/O库
【之前的输入输出函数并没有特定性,而是适用于通常情况下的I/O;标准I/O库针对I/O的具体情况,分类给出了特定的I/O函数;从一定角度而言,是“高级”的I/O函数。另外,与此相关的“流”的概念是和指针很相似的,也是一种“抽象”。】
- 总述:这个库提供了unixI/O较高级别的替代。
- 类型:
- 打开和关闭文件的函数(fopen和fclose);
- 读和写字节的函数(fread和fwrite);
- 读和写字符串的函数(fgets和fputs)
- 流的应用: 一个流就是指向一个FILE类型的结构的指针(比如,每有一个ASNI C文件打开,都会同时打开STDIN,STDOUT,STDERR三个流)。
- 含义:流是对文件描述符和流缓冲区的抽象。(流缓冲区的目的和RIO类似,就是减少开销较高的unix系统调用的数量)
3.关于输入与输出函数的一些矛盾点
【C语言编程的时候,经常会因为输入域输出交叉调用导致输入或者输出函数不能取到想要的值】
- 输入函数不能紧跟在输出函数之后——如果输出函数之后没有加上fflush,fseek,fsetpos等。前者是清空与流相关的缓冲区;后两者用lseek函数重置当前的文件位置;
- 输出函数不能紧跟在输入函数之后——如果输入函数之后没有fseek,fsetpos,rewind等。
4.基于错误处理包装函数
- 思想:给定的基本级系统函数foo,我们有相同参数的、函数名大写的包装函数Foo;包装函数调用基本函数并检查错误。如果发现了错误,包装函数就终止进程并返回一条信息;当基本函数无误的时候,包装函数就返回调用者。(包装函数被封装在源文件csapp.c中)
5.unix系统中的错误处理
-
unix风格:例如fork函数和外套函数,返回值既包括错误代码,又包括有用的结果。
if((pid = wait(NULL))<0) { fprintf(stderr,"wait error:%s\n",strerror(errno));//将errno设置为指向错误原因的代码 exit(0); }
- Posix风格:例如pthread,函数只返回调用成功(0)或者失败(非0),任何有用的信息都返回在通过调用引用进来的参数中。
- DNS风格:gethostbyname和gethostbyaddr检索NDS(域名系统)库;它们在错误的时候会返回NULL,并设置全局变量h_errno。
-
错误处理包装函数
-
unix风格
pid_t Wait(int *status) { pid_t pid; if(pid = wait(status)<0) unix_error("wait error"); return pid; }
-
Posix风格
void Pthread_detach(pthread_t tid) { int rc; if(rc=pthread_detach(tid) != 0) posix_error(rc,"Pthread_detach error"); }
-
DNS风格
struct hostent *Gethostbyname(const char *name) { struct hostname *p; if((p = gethostbyname(name)) == NULL) dns_error("Gethostbyname error"); return p; }
-
二、练习题
1.如何使用dup2将标准输入重定向到描述符5?
【参考上面的函数,标准输入的描述符为0,则使用:
int dup2(5,0);
进行重定向。】
2.假设磁盘文件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,所以输出的是第二个字母(之前的第一个字母‘f’已经被读过了):‘o’】
三、课堂讲解重点
1.man -k应用:
2.关于父子进程并发执行的问题:
【当父进程打开子进程之后,父子进程并发执行,而且,二者结束的先后顺序是不可控制的;最后,当子进程被打开之后,父子进程之后的部分是一样的;而且,最后的结果先后无法区分】
四、问题解决
-
1.开始运行练习题10.1的代码时,编译出错,显示是因为无法找到“csapp.h”文件
#include "csapp.h" int main() { int fd1,fd2; fd1=Open("foo.txt",O_RDONLY,0); Close(fd1); fd2=Open("baz.txt",O_RDONLY,0); printf("fd2=%d\n",fd2); exit(0); }
通过网上搜索,发现一篇博客给出了解答:
这一周老师给布置了一个有关IO的Open函数的实验,叫我们自己到linux上去运行一下,结果在csapp.h这个头文件上纠结了好久,在这里特别总结一下,留个纪念. 是csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载。这是《深入理解计算机系统》配套网站,但有个疑问是csapp.h这个 是作者写的?还是出自unix的源代码了?但毫无疑问他给我们写一些程序的编写带来了方便,有了它我们就没必要在写那么多头文件了,一个就搞定。至于出处的话,就不纠结了,会用就行。
在linux下要怎么使用头文件了,linux应该没有自带csapp.h,所以要自己导入,我用的是fedora的,要放到 /usr/include的文件夹里面。打开后这里面有好多头文件... (ubuntu下是/usr/lib,其他版本的linux应该也是在usr的目录下吧)。另外还有一点,要在头文件的#end if前面加上一句#include <csapp.c>,因为那个头文件要把csapp.c文件包含进去 这样的话就可以用了。
还有就是因为csapp.c中有关于线程的头文件,在用gcc的时候最后要加上-lpthread 如 # gcc -o Ex Ex.c -lpthread
- 2.在开始进行关于头文件为csapp.h的编程时,我遇到了如下的问题:
【也就是无法通过“复制”——“粘贴”完成csapp.h的添加】
【经过小组提问,发现可以通过命令行终端的mv命令进行操作】
- 3.在我进行第三次尝试的时候,新的问题又出现了:linux系统无法识别U盘,也无法和主机共享文件夹。导致csapp.h文件无法拷贝到虚拟机。 通过“百度经验”,我按照指导下载并安装了virtualbox 4.3.26 r98988版本的扩展包,以此安装增强功能;然而安装失败。
- 4.通过请教老师,发现是由于本机电脑为win8.1,装载虚拟机限制比较多。此后,我又借用其他同学的电脑,在苹果IOS系统下进行尝试。
【结果失败】
- 5.仔细研究之后,我发现删除掉csapp.h和csapp.c之后重新尝试,则可以运行出结果。(另:虚拟机与主机的文件交互目前还在尝试)
心得
本次学习是对之前学习的精细化过程;因为知识性的新内容不多,所以我就把大部分精力放在了实践上。对于课本上的代码,尽量去打出来运行;对于之前想尝试但一直没有尝试的linux命令或者功能学习,尽力去练习。看似抓住的不多,然而不断的尝试和失败再到成功,也是很有教育意义的。