异常控制流

控制流 分为平滑的控制流(相邻的地址跳转) 和 跳转、调用、返回(控制流突变)


突变控制流称为 异常控制流(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文本格式输出大量内核数据结构的内容,用户可以读取。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值