2017-2018-1 20155301 《信息安全系统设计基础》第5周学习总结
教材学习内容总结
- ECF是操作系统用来实现I/O、进程和虚拟内存的基本机制。
- 应用程序通过使用一个叫做陷阱或者系统调用的ECF形式,向操作系统请求服务。比如,向磁盘写数据、从网络读取数据、创建一个新进程,以及终止当前进程,都是通过应用程序调用来实现的。理解基本的系统调用机制将帮助理解这些服务是如何提供给应用程序的。
- 操作系统为应用程序提供了强度大的ECF机制,用来创建新进程、等待进程终止、通知其他进程系统中的异常事件,以及检测和响应这些事件。
- 异常是异常控制流的一种形式,它一部分由硬件实现,一部分有操作系统实现。
- 系统中可能的每种类型的一场都分配了一个唯一的非负整数的一场号,其中一些号码有处理器的设计者分配,其他号码是由操作系统内核的设计者分配。
- 一场可以分为四类:中断、陷阱、故障和终止
类型 | 原因 | 异步/同步 | 返回行为 |
---|---|---|---|
中断 | 来自I/O设备的信号 | 异步 | 总是返回到下一条指令 |
陷阱 | 有意的异常 | 同步 | 总是返回到下一条指令 |
故障 | 潜在可恢复的错误 | 同步 | 可能返回到当前指令 |
终止 | 不可恢复的错误 | 同步 | 不会返回 |
-
逻辑控制流,在系统中通常有许多其他程序在运行,进程也可以向每个程序提供一种假象,好像他在都在独占的使用处理器。如果想用调试器单步执行程序,我们会看到一系列的程序计数器(PC)的值,这些值唯一地对应于包含在程序的可执行目标文件中的指令,或是包含在运行时动态连接到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流,或者简称逻辑流。
-
并发流,一个逻辑流的执行在时间上与另一个流重叠,成为并发流,这两个流被称为并发的运行。
-
系统调用错误处理,当Unix系统级函数遇到错误时,他们通常会返回-1,并设置全局整数变量errno来表示什么出错了。
-
获取进程ID,每个进程都有一个唯一的正数进程ID(PID)。getpid函数返回调用进程的PID。
-
每一个Linux文件都有一个类型来表明他在系统中的角色
1.普通文件包含任意数据。应用程序常常要区分文本文件和二进制文件,文本文件是只含有ASCII或Unicode字符的普通文件;二进制文件是所有其他的文件。对内核而言,文本文件和二进制文件没有区别。
Linux文本文件包含了一个文本行序列,其中每一行都是一个字符序列,以一个新行符“ ”结束。新行符与ASCII的换行符(LF)是一样的,其数字值为0x0a。
2.目录是包含一组链接的文件,其中每个链接都将一个文件名映射到一个文件,这个文件可能是另一个目录。每个目录至少含有两个条目:“.”是到该目录自身的链接,以及“..”是到目录层次结构中父目录的链接。你可以用mkdir命令创建一个目录,用ls查看其内容,用rmdir删除该目录。
3.套接字是用来与另一个进程进行跨网络通信的文件 -
打开和关闭文件,进程是通过调用open函数来打开一个已存在的文件或者创建一个新的我文件.
-
关于fork()函数的作用
例如:
为什么两行都打印出来了?在我想来,不管pid是多少,都应该只有一行才对。
原因在于fork之后,操作系统会复制一个与父进程完全相同的子进程,虽说是父子关系,但是在操作系统看来,他们更像兄弟关系。
这2个进程共享代码空间,但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,但只有一点不同,如果fork成功,子进程中fork的返回值是0,父进程中fork的返回值是子进程的进程号,如果fork不成功,父进程会返回错误。可以这样想象,2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了。这也是fork为什么叫fork的原因。 -
关于exec()函数
fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。
在Linux中并没有exec函数,而是有6个以exec开头的函数族,下表列举了exec函数族的6个成员函数的语法。
所需头文件 | #include <unistd.h> |
---|---|
函数说明 | 执行文件 |
函数原型 | int execl(const char *path, const char *arg, ...) |
函数原型 | int execv(const char *path, char *const argv[]) |
函数原型 | int execle(const char *path, const char *arg, ..., char *const envp[]) |
函数原型 | int execve(const char *path, char *const argv[], char *const envp[]) |
函数原型 | int execlp(const char *file, const char *arg, ...) |
函数原型 | int execvp(const char *file, char *const argv[]) |
函数返回值 | 成功:函数不会返回 |
函数返回值 | 出错:返回-1,失败原因记录在error中 |
要记住这六个函数之间的区别,就要搞清楚 “l” 、“v”、“p”、“e”代表的含义
“l”表示参数以列表的形式表示;
“v”表示参数以数组的形式表示;
“p”表示在PATH中搜索执行文件;
“e”表示可附加环境参数。
execlp、execvp这两个函数第一个形参是名为file表示可以只列出文件名就可以了,不用指出它的路径。
- wait函数说,当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件,这种信号也是内核向父进程发的异步通知。父进程可以忽略该信号,或者提供一个该信号发生时即被调用执行的函数(信号处理程序)。
父进程同步等待子进程退出时则调用wait函数,此时父进程可能会有如下三种情形:
阻塞(如果其所有子进程都还在运行)。
带回子进程的终止状态立即返回(如果已有一个子进程终止,正等待父进程取其终止状态)
出错立即返回(如果它没有任何子进程)。
- wait函数
所需头文件 | #include <sys/types.h> #include <sys/wait.h> |
---|---|
函数说明 | wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则status可以设成NULL |
函数原型 | pid_t wait (int *status) |
函数传入值 | 这里的status 是一个整型指针,是该子进程退出时的状态:1.status 若为空,则代表不记录子进程结束状态。2.status 若不为空,则由status记录子进程的结束状态值。 |
函数返回值 | 成功返回子进程识别码(PID) |
函数返回值 | 出错-1,失败原因存于errno中 |
- waitpid函数
所需头文件 | #include <sys/types.h> #include <sys/wait.h> |
---|---|
函数说明 | waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status可以设成NULL。参数pid为欲等待的子进程识别码 |
函数原型 | pid_t waitpid(pid_t pid,int * status,int options) |
函数传入值 | pid<-1:等待进程组识别码为pid绝对值的任何子进程 |
函数传入值 | pid=-1: 等待任何子进程,相当于wait() |
row 1 col 1 | pid=0:等待进程组识别码与目前进程相同的任何子进程 |
row 2 col 1 | pid=>0:等待任何子进程识别码为pid的子进程 |
函数传入值 | 参数options可以为0 或下面的OR 组合 |
函数传入值 | 参数options,WNOHANG:如果没有任何已经结束的子进程则马上返回,不予以等待。此时返回值为0 |
函数传入值 | 参数options,WUNTRACED:如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会 |
函数传出值 | 同wait函数 |
函数返回值 | 成功返回子进程识别码(PID) |
函数返回值 | 成功使用选项WNOHANG且没有子进程退出返回0 |
函数返回值 | 出错-1,失败原因存于errno中 |
-
exit函数,
exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束return()是当前函数返回,当然如果是在主函数main,自然也就结束当前进程了,如果不是,那就是退回上一层调用。在多个进程时.如果有时要检测上进程是否正常退出的就要用到上个进程的返回值..exit(1)表示进程正常退出. 返回 1;
exit(0)表示进程非正常退出. 返回 0.
进程环境与进程控制(1): 进程的开始与终止
函数原型:int main(int argc, char *argv[]); -
open函数
int open(char* filename,int flags,mode_t mode)
opne函数将filename转换为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符。flags参数指明了进程打算如何访问这个文件:
1.O_RDONLY:只读.
2.O_WRONLY:只写
3.O_RDWR:可读可写
4.O_CREAT:如果文件不存在,就创建他的一个截断的空文件
5.O_TRUNC:如果文件已经存在,就截断它。
6.O_APPEND:在每次写操作前,设置文件位置到文件的结尾处。
- 进程通过调用close函数关闭一个打开的文件,若成功则返回0,若出错则为返回-1
- 应用程序是通过分别调用read和write函数来执行输入输出的:
ssize_t read(int fd,void *buf,size_t n);
ssize_t write(int fd,const void *buf,size_t n);
关于read函数
返回值:成功则返回读的字节数,EOF返回0,出错返回-1。
fd:文件描述符
buf:存储器位置
n:最多从当前文件位置拷贝n个字节到存储器位置buf
关于write函数
返回值:成功则返回写的字节数,出错返回-1。
fd:文件描述符
buf:存储器位置
n:最多从存储器位置buf拷贝n个字节到当前文件位置
-
共享文件,内核用三个相关的数据结构来表示打开的文件:
1.描述符表:每个进程都有独立的描述符表,由进程打开的文件描述符来索引,每个打开的描述符表项指向文件表中的一个表项。
2.文件表:所有进程共享,表项组成包括当前文件位置、引用计数、一个指向v-node表中对应表项的指针。引用计数为0时,内核会删除这个文件表表项。
3.v-node表:所有进程共享,每个表项包含stat结构中的大多数信息。
教材学习中的问题和解决过程
书p603rio_read函数中,erro!=EINTR我感觉应该是erro==EINTR
代码调试中的问题和解决过程
代码托管
上周考试错题总结
- 错题1及原因,理解情况
- 错题2及原因,理解情况
- ...
结对及互评
点评模板:
- 博客中值得学习的或问题:
- xxx
- xxx
- ...
- 代码中值得学习的或问题:
- xxx
- xxx
- ...
- 其他
本周结对学习情况
[20155317](http://www.cnblogs.com/wxwddp/p/7671075.html)
![image](http://note.youdao.com/favicon.ico)
- 结对学习内容
- XXXX
- XXXX
- ...
其他(感悟、思考等,可选)
xxx
xxx
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:XX小时
-
实际学习时间:XX小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)