管家婆用户进程中发生浮点异常错误_深入理解计算机系统:进程

导语:这是篇读书笔记,每次重读CSAPP都有新的认知,尤其是在进入了后台通道之后才感受到每天和进程打交道的感觉是如此深刻。
ab84a07fb59f98cfb9da5e4a84f497ca.png

0x00 What is Process?

742a414a1d0f8cc7200a5dce0677fe91.png

[ system structure ]

  • 进程(Process)

经典定义是一个执行中的程序的实例,操作系统对一个正在运行的程序的一种抽象。并发运行,指的是一个进程的指令和另一个进程的指令交错执行。操作系统实现这种交错执行的机制称为上下文切换。

  • 线程(Thread)

一个进程可以由多个线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。

  • 内核(Kernel)

一个计算机程序,用来管理软件发出的数据I/O(输入与输出)要求,将这些要求转译为数据处理的指令,交由中央处理器(CPU)及计算机中其他电子组件进行处理,是现代操作系统中最基本的部分。

  • 外壳(Shell)

指“为使用者提供使用者界面”的软件,通常指的是命令行界面的解析器。一般来说,这个词是指操作系统中提供存取内核所提供之服务的程式。Shell也用于泛指所有为用户提供操作界面的程序,也就是程序和用户交互的层面。内核不提供交互。

  • 抢占(Preemption)

分为非抢占式和抢占式。根据调度主体分用户抢占与内核抢占。

非抢占式(Nonpreemptive)——让进程运行直到结束或阻塞的调度方式。

抢占式(Preemptive)——允许将逻辑上可继续运行的在运行过程暂停的调度方式。可防止单一进程长时间独占CPU。

  • 异常控制流(ECF,Exceptional Control Flow)

ECF发生在硬件层,操作系统层,应用层。控制转移(control transfer)是指程序计数器对应的指令序列的跳转,控制转移序列的叫做处理器的控制流(control flow)。

某些如跳转、调用和返回是为了使得程序对内部状态变化(event)做出反应而设计的机制,系统通过使控制流发生突变对发生各种状态变化。

Exceptions

任何情况下,处理器检测到event发生,通过异常表(exception table)跳转到专门处理这类事件的操作系统子程序(exception handler)。

异步异常由事件产生,同步异常是执行一条指令的直接产物。

类别包含中断(异步)陷阱(同步)故障(同步)终止(同步)

  • 中断——异步发生,处理器IO设备信号的结果。
  • 陷阱——有意的异常。最重要的用途是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用。
  • 故障——潜在可恢复的错误造成的结果。如果能被修复,则重新执行引起故障的指令,否则终止。
  • 终止——不可恢复的致命错误造成的结果。

有高达256种不同的异常类型,如出发错误(0)、一般保护故障(13)、缺页(14)、机器检查(18)、操作系统定义的异常(32-127,129-255)、系统调用(0x80)。

我们常见的段故障(Segmentation fault),是一般保护故障(异常13),通常是因为一个程序引用了一个未定义的虚拟存储器区域,或者因为程序试图写一个只读的文本段。

6c7adb4148882ef46771c23aec354f04.png

[ Examples of popular system calls ]

Processes

  • 逻辑控制流(Logical Control Flow)

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

逻辑流看起来就像是在独占处理器地执行程序,每个进程执行逻辑流的一部分然后就被抢占,实际上处理器通过上下文保护好进程间的信息,在不同的进程中切换。

  • 并发流(Concurrent Flows)

并发流指逻辑流在执行时间上与另一个流重叠,多个就叫并发(concurrent)。

一个进程和其他进程轮流运行叫多任务(multitasking)。

进程占有CPU执行控制流的每一个时间段叫时间片(time slice)。

多任务也叫做时间分片(time slicing)。

如果两个流并发运行在不同的处理器或者计算机,称为并行流(parallel flow)。

  • 私有地址空间(Private Address Space)

一般,进程间地址空间读写保护。进程地址空间32位进程,代码段从0x08048000开始,64位进程从0x00400000开始:

4267639d27a651b927767480a83717c4.png

[ Process address space ]

  • 用户模式和内核模式(User and Kernel Modes)
  • 通过控制寄存器中的模式位(mode bit)描述进程当前享有的特权。
  • 内核模式:(超级用户)可执行指令集中任何指令,并且可以访问系统中任何存储器位置。
  • 用户模式:不允许执行特权指令,不允许直接引用地址空间中内核区内的代码和数据,任何尝试都会引发致命保护故障。可以通过系统调用接口间接访问内核代码和数据。
  • 上下文切换(Context Switches)
  • 内核为每个进程维持一个上下文(context),是内核重新启动一个被抢占的进程所需的状态。包括:
  • 通用目的的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构(地址空间的页表、有关当前进程信息的进程表、进程已打开文件的信息的文件表)
  • 内核调度器(scheduler)负责调度进程,抢占当前进程,重新开始先前被抢占的进程。

0x01 101 Inside Process

Process Control

如何控制进程?

PID

pid > 0

#include  // for pid_t#include ​pid_t getpid(void); // 获取进程IDpid_t getppid(void); // 获取父进程ID

Creating and Terminating Process

从程序角度来看,进程总处于以下三种状态:

  • Running——要么处于CPU执行中,要么处于等待被执行且最终会被内核调度。
  • Stopped——进程被挂起(suspend),且不会被调度。当收到SIGSTOP、SIGTSTP、SIGTTIN或者SIGTTOU信号时,进程停止,直到收到SIGCONT信号,进程再次开始运行。
  • Terminated——进程永远停止了。三种原因导致终止:
  1. 收到一个默认行为时终止进程的信号;
  2. 从主程序返回;
  3. 调用exit。
#include #include /* 创建子进程* 返回:子进程=0,父进程=子进程PID,出错=-1*/pid_t fork(void);​#include void exit(int status);

父进程通过调用fork创建一个新的运行子进程,最大的区别在于不同的PID。

  • fork():一次调用,返回两次。
  1. 在调用进程中(父进程),返回子进程PID;
  2. 在新创建的子进程中,在子进程中返回0。
  • 并发执行:父子进程是并发运行的独立进程。
  • 相同但是独立的地址空间。子进程与父进程用户级虚拟地址空间相同的拷贝,相同的本地变量值、堆、全局变量、以及代码。如代码中print出来不一样的x。
  • 共享文件:任何打开文件描述符相同的拷贝,如stdout。
int main() { pid_t pid; int x = 1;​ pid = fork(); // 在此处分裂出了两条时间线! if (pid == 0) {// 子进程 printf("child: x=%d
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值