控制流 分为平滑的控制流(相邻的地址跳转) 和 跳转、调用、返回(控制流突变)
突变控制流称为 异常控制流(ECF)
异常
异常就是控制流中状态的突变,处理器检测到事件发生时,会通过一张 异常表 的跳转表,间接调用异常处理程序。
处理完之后,有三种可能性:
1、将控制返回当前指令,即事件发生时正在执行的指令
2、将控制返回给如果没有发生异常的下一个指令
3、处理程序终止被中断的程序
异常分为四种:
1、中断
只有中断是异步的,是来自处理器外部的I/O设备的信号的结果。
是在当前指令执行完之后才进行中断处理程序。
2、陷阱和系统调用
有意的异常,是执行指令的结果。用途是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用。
用户经常需要向内核请求服务,比如读文件,fork,execve等,为了允许对这些内核服务的受控的访问,处理器提供了一条特殊的“syscall n”指令来请求服务n。这哥指令导致一个异常处理程序的陷阱,这个处理程序解析参数,并调用适当的内核程序。
系统调用运行在内核模式中。
3、故障
由错误情况引起,可能被故障处理程序修正。
经典的是缺页异常,处理是从磁盘中加载适当的页面,然后将控制返回给引起故障的指令。再重新运行这个指令。
4、终止
不可恢复的致命错误导致,通常是一些硬件错误。
进程
经典定义:一个执行中程序的实例
进程提供给应用程序的关键抽象:
一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占地使用处理器。
一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用内存系统。
一个流的执行在时间上与另一个流重叠,称为并发流。
如果两个流并发的运行在不同的处理器核或者计算机上,那么是并行流。并行流是并发流的子集
内核模式的进程执行任何指令,访问任何地址空间。
上下文是内核重启一个被强占的进程所需的状态。
系统调用处理函数
错误检查函数,可以使用错误处理包装函数来简化代码。
进程控制
void exit(int status); 用来终止进程
子进程继承父进程的所有打开文件,所以都能输出显示在屏幕上。
waitpid() 等待子进程终止或停止
int pause(void); 让调用函数休眠,直到接受到一个信号。
int execve(...) 在当前进程的上下文中加载并运行一个新程序。与fork有本质区别。
信号
信号通知进程系统中发生了一个某种类型的事件。
任何时刻,一种类型最多只会有一个待处理信号。
当一种信号被阻塞,仍可以被发送,但是待处理信号不会被接受,直到进程取消对这种信号的阻塞。
pid_t getpgrp(void) 获得进程组Id
int kill(pid_t pid, int sig); 发送SIGKILL信号给其他进程
unsigned int alarm(unsigned int secs) 安排内核在secs秒后发送SIGALRAM信号给自己
sighandler_t signal(int signum, sighandler_t handler); 改变和信号signum相关联的行为,handler就是信号处理程序
int sigprocmask(int how, const sigset_t *set, sigset_t * oldset); 设置阻塞信号集合,阻塞的意思就是当信号来了不处理
编写信号处理程序:
处理程序和主程序并发运行,因此:
G0:处理程序尽可能简单
G1:处理程序中只调用异步信号安全的函数,要么是可重入的(只访问局部变量),要么不能被信号处理程序中断(比如说write函数)。
G2:保存和恢复errno。因为异步信号安全的函数在出错返回会设置errno,这样会干扰主程序依赖于errno的部分。
G3:阻塞所有信号,保护对共享全局数据结构的访问。
G4:用volatile声明全局变量。告诉编译器永远不要缓存这个变量。
G5:用sig_atomic_t 声明标志,常见处理程序中,会有一个全局标志来记录收到信号,volatile sig_atomic_t flag,可以保证原子性。
正确的信号处理:
信号是不会排队的,如果有一个未处理的信号就表明至少有一个信号到达了。因此不可以用信号来对事件计数!
一定要注意信号处理程序和主程序的竞争。
可以用:
int sigsuspend(const sigset_t * mask); 暂时用mask替换当前的阻塞集合,然后挂起该进程,直到收到一个信号,其行为是要么运行一个处理程序,要么终止该进程。
非本地跳转:
int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int retval);
void longjmp(jmp_buf env, int savesigs); 每次调用longjmp就跳回setjmp,setjmp返回值是longjmp的savesigs。
/proc:一个虚拟文件系统,以askii文本格式输出大量内核数据结构的内容,用户可以读取。