2018-2019-1 20165226 《信息安全系统设计基础》第7周学习总结
目录
一、教材学习内容总结
1、了解异常及其种类
异常
- 异常是异常控制流的一种形式,它一部分是由硬件实现的,一部分是有操作系统实现的。
- 异常:控制流中的突变,用来响应处理器状态中的某些变化。
- 当异常处理程序完成处理后,根据引起异常的事件的类型,会发生以下三种情况的一种:
- 处理程序将控制返回给当前指令Icurr,即当事件发生时正在执行的指令。
- 处理程序将控制返回给Inext,即如果没有发生异常将会执行的下一条指令。
- 处理程序终止被中断的程序。
异常类别
- 中断(异步)
- 陷阱(同步)
- 故障(同步)
- 终止(同步)
类别 | 原因 | 异步/同步 | 返回行为 |
---|---|---|---|
中断 | 来自I/O设备的信号 | 异步 | 总是返回到下一条指令 |
陷阱 | 有意的异常 | 同步 | 总是返回到下一条指令 |
故障 | 潜在可恢复的错误 | 同步 | 可能返回到当前的指令 |
终止 | 不可恢复的错误 | 同步 | 不会返回 |
异常处理
- 异常表基址寄存器:异常表的起始地址存放的位置。
- 异常与过程调用的异同:
- 过程调用时,在跳转到处理器之前,处理器将返回地址压入栈中。然而,根据异常的类型,返回地址要么是当前指令,要么是下一条指令。
- 处理器把一些额外的处理器状态压入栈里,在处理程序返回时,重新开始被中断的程序会需要这些状态。
- 如果控制从一个用户程序转移到内核,那么所有这些项目都被压到内核栈中,而不是压到用户栈中。
- 异常处理程序运行在内核模式下,意味着它们对所有的系统资源都有完全的访问权限。
2、理解进程和并发的概念
进程
- 是一个执行中的程序的实例,系统中的每个程序都是定义在运行在某个进程的上下文中的。异常是允许操作系统提供进程的概念所需要的基的本构造块。
- 进程提供给应用程序的关键抽象:
- 一个独立的逻辑控制流,独占地使用处理器;
- 一个私有的地址空间,独占地使用存储器系统。
并发
- 并发流:一个逻辑流的执行在时间上与另一个流重叠。
- 并发:多个流并发地执行的一般现象。
- 多任务:一个进程和其他进程轮流运行的概念。
- 时间片:一个进程执行它的控制流的一部分的每一时间段。
- 多任务也叫时间分片。
- 并行流:如果两个流并发的运行在不同的处理器核或者计算机上
3、掌握进程创建和控制的系统调用及函数使用:fork,exec,wait,waitpid,exit,getpid,getppid,sleep,pause,setenv,unsetenv,
进程创建
- 父进程通过调用fork函数创建一个新的运行的子进程。
- 子进程和父进程的异同:
- 异:有不同的PID
- 同:用户级虚拟地址空间,包括:文本、数据和bss段、堆以及用户栈。任何打开文件描述符,子进程可以读写父进程中打开的任何文件。
- fork函数: 因为父进程的PID总是非零的,返回值就提供一个明确的方法来分辨程序是在父进程还是在子进程中执行。
- fork函数的特点:
- 调用一次,返回两次
- 并发执行
- 相同的但是独立的地址空间
- 共享文件
**回收子进程
- 一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止。默认地,当option=0时,waitpid挂起调用进程的执行,直到它的等待集合中的一个子进程终止。
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);
//返回:若成功,返回子进程的PID;若WNOHANG,返回0;若其他错误,返回-1。
- 判定等待集合的成员,通过参数pid来确定的:
- pid>0:等待集合是一个单独的子进程,进程ID等于pid。
- pid=-1:等待结合就是由父进程所有的子进程组成的。
- 错误条件
- 如果调用进程没有子进程,那么waitpid返回-1,并设置errno为ECHILD
- 如果函数被一个信号中断,那么返回-1,并设置errno为EINTR。
- wait函数:调用wait(&status)等价于调用waitpid(-1.&status,0)
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
//返回:若成功,返回子进程的PID;若错误,返回-1。
让进程休眠
- sleep函数:将进程挂起一段指定的时间
#include <unistd.h>
unsigned int sleep(unsigned int secs);
//返回:还要休眠的秒数
- pause函数:让调用函数休眠,直到该进程收到一个信号
#include <unistd.h>
int pause(void);
//返回:总是-1
加载并运行程序
- execve函数:在当前进程的上下文中加载并运行一个新程序。参数相关说明:
- filename:可执行目标文件
- argv:带参数列表
- envp:环境变量列表
特点:execve调用一次从不返回
include <unistd.h>
int execve(const char filename,const char argv[],const char *envp[]);
//返回:若成功,则不返回,若错误,返回-1
- getenv函数:在环境数组中搜素字符串“name =VALUE”,若找到了,就返回一个指向value的指针,否则它就返回NULL。
include <stdlib.h>
char getenv(const char name);
//返回:存在,返回指向name的指针,若无匹配的,为NULL
4、理解信号机制:kill,alarm,signal,sigaction
- 进程组
- 每个进程都只属于一个进程组,进程组是由一个正整数进程组ID来标识的。getpgrp函数返回当前进程的进程组ID:默认地,一个子进程和它的父进程同属于一个进程组。
- 用/bin/kill/程序发送信号 一个为负的PID会导致信号被发送到进程组PID中的每个进程。
- 从键盘发送信号
- 作业:表示对一个命令行求值而创建的进程。外壳为每个作业创建一个独立的进程组。
- 用kill函数发送信号
- 进程通过调用kill函数发送信号给其他的进程。父进程用kill函数发送SIGKILL信号给它的子进程。
- 用alarm函数发送信号
- 在任何情况下,对alarm的调用都将取消任何待处理的闹钟,并且返回任何待处理的闹钟在被发送前还剩下的秒数。
5、掌握管道和I/O重定向:pipe, dup, dup2
- 重定向I/O的是shell而不是程序。
- 管道是一个队列,当从管道读走数据后,数据就不存在了。如果两个进程都对管道进行读操作,当一个进程读走一些数据后,另一个进程读到的是后面的内容。
- dup 和 dup2 是用来复制一个文件描述符,dup只有一个参数,dup2有两个参数。通常用来重定向进程的stdin(文件描述符0),stdout(文件描述符1), stderr(文件描述符2)。
二、课堂测试补做
练习题
参考伪代码实现ls的功能,提交代码的编译,运行结果截图,码云代码链接。
打开目录文件- 代码
#include<sys/types.h>
#include <stdio.h>
#include<dirent.h>
#include<unistd.h>
int main(int argc,char **argv)
{
DIR * dir;
struct dirent * ptr;
int i;
if(argc==1)
dir=opendir("./");
else
dir=opendir(argv[1]);
while((ptr=readdir(dir))!=NULL)
{
printf("d_name: %s\n",ptr->d_name);
}
closedir(dir);
return 0;
}
三、代码托管与统计
****
代码托管
四、学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 87/87 | 2/2 | 20/20 | |
第二周 | 71/158 | 1/3 | 12/32 | |
第三周 | 100/258 | 2/5 | 13/45 | |
第四周 | 3265/9750 | 2/7 | 15/60 | |
第五周 | 282/9786 | 1/8 | 8/68 | |
第六周 | 1980/13996 | 2/10 | 8/76 | |
第七周 | 488/14484 | 1/11 | 8/84 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
计划学习时间:8小时
实际学习时间:8小时
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)