• 2017-2018-1 20155208 《信息安全系统设计基础》第六周学习总结


    2017-2018-1 20155208 《信息安全系统设计基础》第六周学习总结

    学习目标

    • 了解异常及其种类
    • 理解进程和并发的概念
    • 掌握进程创建和控制的系统调用及函数使用:fork,exec,wait,waitpid,exit,getpid,getppid,sleep,pause,setenv,unsetenv,
    • 理解数组指针、指针数组、函数指针、指针函数的区别
    • 理解信号机制:kill,alarm,signal,sigaction
    • 掌握管道和I/O重定向:pipe, dup, dup2

    教材学习内容总结

    8.1 异常

    • 异常就是控制流中的突变,用来响应处理器状态中的某些变化。

    • 异常控制流:现代系统通过使控制流发生突变来对这些情况作出反应。

    • 8.1.1 异常处理

    • 系统中可能的每种类型的异常都分配了一个唯一的非负整数的异常号。

    • 异常号的分配:

      1、处理器的设计者:被除零、缺页、存储器访问违例、断点以及算数溢出。

      2、操作系统内核的设计者分配的:系统调用和来自意外的I/O设备的信号。

    • 异常号:到异常表中的索引异常表基址寄存器:异常表的起始地址存放的位置。3、异常与过程调用的异同:

      1、过程调用时,在跳转到处理器之前,处理器将返回地址压入栈中。然而,根据异常的类型,返回地址要么是当前指令,要么是下一条指令。

      2、处理器把一些额外的处理器状态压入栈里,在处理程序返回时,重新开始被中断的程序会需要这些状态。

      3、如果控制从一个用户程序转移到内核,那么所有这些项目都被压到内核栈中,而不是压到用户栈中。

      4、异常处理程序运行在内核模式下,意味着它们对所有的系统资源都有完全的访问权限。

    • 8.1.2异常的类别

    • 中断: 来自I/O设备的信号,异步,总是返回到下一条指令

    • 陷阱: 有意的异常,同步,总是返回到下一条指令

    • 故障: 潜在可恢复的错误,同步,可能返回到当前指令

    • 终止: 不可恢复的错误,同步,不会返回

    8.2 进程

    • 异常是允许操作系统提供进程的概念所需要的基本构造块。

    • 进程:一个执行中的程序的实例。

    • 上下文是由程序正确运行所需要的状态组成的,这个状态包括存放在存储器中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。

    • 进程提供给应用程序的关键抽象:一个独立的逻辑控制流,独占地使用处理器;一个私有的地址空间,独占地使用存储器系统。

    • 8.2.1 逻辑控制流

      程序计数器:唯一的对应于包含在程序的可执行目标文件中的指令,或者是包含在运行时动态链接到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流,简称逻辑流。

    • 8.2.2 并发流

    • 并发流:一个逻辑流的执行在时间上与另一个流重叠。

    并发:多个流并发地执行的一般现象。

    多任务:一个进程和其他进程轮流运行的概念。

    时间片:一个进程执行它的控制流的一部分的每一时间段。

    多任务也叫时间分片。

    • 并行流:如果两个流并发的运行在不同的处理器核或者计算机上

    • 8.2.3 私有地址空间

    • 这个空间中某个地址相关联的那个存储器字节是不能被其他进程读或者写的

    • 8.2.4 用户模式和内核模式

    • 当设置了模式位时,进程就运行在内核模式中

    • 没有设置模式位时,进程就运行在用户模式中。用户模式中的进程不允许执行特权指令。

    • 进程从用户模式变位内核模式的唯一方法是通过诸如中断、故障或者陷入系统调用这样的异常。 /proc文件系统允许用户模式进程访问内核数据结构的内容

    • 8.2.5 上下文切换

    • 上下文切换:是较高形式的异常控制流来实现多任务

    • 调度:在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占的进程。这种决定叫做调度

    • 当内核代表用户执行系统调用时,可能会发生上下文切换。如果系统调用因为等待某个事件发生阻塞,那么内核可以让当前进程休眠,切换到另一个进程

    • 中断也可能引发上下文切换

    8.3 系统调用错误处理

    • 错误处理包装函数:包装函数调用基本函数,检查错误,如果有任何问题就终止。 8.4 进程控制

    • 8.4.1获取进程ID

      每个进程都有一个唯一的正数进程ID gitpid函数返回调用进程的PID,getppid函数返回它的父进程的PID(创建调用进程的进程)

    • 8.4.2 创建和终止进程

      进程状态:运行、停止、终止 exit函数以status退出状态来终止进程 fork函数

      父进程通过调用fork函数创建一个新的运行子进程

      当父进程调用fork时,子进程可以读写父进程中打开的任何文件

      父进程和子进程之间最大的区别在于有不同的PID

      调用一次,返回两次

      并发执行

      相同但是独立的地址空间

      共享文件

    • 8.4.3 回收子进程 僵死进程没有运行,他们仍然消耗系统的存储器资源 一个进程可以通过调用waitpid函数来等待它的子进程终止或停止

    1、判定等待集合的成员(由参数pid确定) pid>0,等待集合就是一个单独的子进程,它的进程ID等于pid pid=-1,等待集合就是由父进程所有的子进程组成的

    2、修改默认行为 WNOHANG:默认行为是挂起调用进程,直到有子进程终止 WUNTRCED:默认行为是只返回已经终止的子进程 WNOHANG|WUNTRCED:立即返回

    3、检查已回收子进程的退出状态

    4、错误条件 如果调用进程没有子进程,那么waitpid返回-1,设置errno为ECHILD 如果waidpid函数被一个信号中断,那么它返回-1,并设置errno为EINTR

    5、wait函数

    6、使用waitpid的示例

    • 8.4.4 让进程休眠

    sleep函数将一个进程挂起一段指定的时间 pause函数让调用函数休眠,直到该进程收到一个信号

    • 8.4.5 加载并运行程序

    execve函数在当前进程的上下文中加载并运行一个新程序,execve调用一次并从不返回 argv参数列表,envp环境变量getenv函数

    8.5 信号

    • 底层的硬件异常是由内核异常处理程序处理的,正常情况下,对用户进程而言是不可见的。

    • 其他信号对应于内核或者其他用户进程中较高层的软件事件

    • 8.5.1 信号术语

      发送信号的两个不同步骤:

    1、发送信号:内核通过更新目的进程上下文中的某个状态,发送(递送)一个信号给目的进程。

    2、接收信号:信号处理程序捕获信号的基本思想。

    发送信号的两个原因:

    1、内核监测到一个系统事件,比如被零除错误或者子进程终止。

    2、一个进程调用了kill函数,显式地要求内核发送一个信号给目的进程。一个进程可以发送信号给它自己。

    待处理信号:一个只发出而没有被接收的信号

    1、一个进程可以有选择性地阻塞接收某种信号。

    2、待处理信号不会被接收,直到进程取消对这种信号的阻塞。

    一个待处理信号最多只能被接受一次,pending位向量:维护着待处理信号集合,blocked向量:维护着被阻塞的信号集合。

    代码调试中的问题和解决过程

    exec

    exec1

    • exec1.c中execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件 如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中 编译运行结果如下,没有返回“* * * man is done. bye”

    exec2

    • 将exevp函数传入的arglist[0]改为arglist[1],此时exevp函数没有调用成功,于是打印出“* * * ls is done. bye”这句话
    • 运行截图如下:

    exec3

    • 函数中execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……最后一个参数必须用空指针(NULL)作结束
    • 运行截图如下:

    fork

    forkdemo1

    • 打印进程pid,然后调用fork函数生成子进程,休眠一秒后再次打印进程id,这时父进程打印子进程pid,子进程返回0。

    forkdemo2

    • 调用两次fork,一共产生四个子进程,所以会打印四个aftre输出。
    • 运行截图如下:

    forkdemo3

    • fork产生子进程,父进程返回子进程pid,不为0,所以输出父进程的那句话,子进程返回0,所以会输出子进程那句话。
    • 运行截图如下:

    forkdemo4

    • 先打印进程pid,然后fork创建子进程,父进程返回子进程pid,所以输出parent一句,休眠十秒;子进程返回0,所以输出child与之后一句。
    • 运行截图如下:

    forkgdb

    • 父进程打印是先打印两句,然后休眠一秒,然后打印一句,子进程先打印一句,然后休眠一秒,然后打印两句。并且这两个线程是并发的,所以可以看到在一个线程休眠的那一秒,另一个线程在执行,并且线程之间相互独立互不干扰
    • 运行截图如下:

    psh

    psh1

    • 输入要执行的指令,回车表示输入结束,然后输入的每个参数对应到函数中,再调用对应的指令。
    • 运行截图:

    psh2

    • 比起1来,多了循环判断,不退出的话就会一直要你输入指令,并且对于子程序存在的状态条件。
    • 运行截图:

    testbuf

    testbuf

    • 用到了fflush(stdout),目的是清空缓冲,强制结果马上显示到屏幕上
    • 运行截图:

    代码托管

    代码上传截图:

    码云链接

    学习进度条

     代码行数(新增/积累)博客量(新增/积累学习时间(新增/累积)
    目标 5000行 30篇 400小时
    第一周 5/5 1/1 8/8
    第二周 120/120 1/1 12/12
    第三周 100/100 1/1 15/15
    第四周 80/80 1/1 9/9
    第五周 50/50 1/1 6/6
    第六周 350/350 1/1 12/12

    参考资料

    《深入理解计算机系统V3》学习指导

  • 相关阅读:
    智能移动机器人背后蕴含的技术——激光雷达
    Kalman Filters
    Fiddler抓HttpClient的包
    VSCode开发WebApi EFCore的坑
    WPF之小米Logo超圆角的实现
    windows react打包发布
    jenkins in docker踩坑汇总
    Using ML.NET in Jupyter notebooks 在jupyter notebook中使用ML.NET ——No design time or full build available
    【Linux知识点】CentOS7 更换阿里云源
    【Golang 报错】exec gcc executable file not found in %PATH%
  • 原文地址:https://www.cnblogs.com/xuzihan/p/7749801.html
Copyright © 2020-2023  润新知