- 控制流
控制处理器从一个指令的执行过程转向另一条指令的指令的执行过程叫做处理器的控制流(control flow)
- 异常控制流(ECF)
- 硬件层 硬件检测异常事件 --> 触发控制流 --> 转移到异常处理程序
- 操作系统层 内核通过上下文切换将将控制从一个用户进程转移到另一个用户进程
- 应用层 一个进程向另一个进程发送信号 --> 接受者会将控制转移到它的一个信号处理程序当中
- 异常
异常(exception)就是控制流中的突变
异常可以分为四类:中断(interrupt)、陷阱(trap)、故障(fault)、终止(abort)
类别 | 原因 | 同步 / 异步 | 返回行为 |
---|---|---|---|
中断 | 来自I / O设备的信号 | 异步 | 总是返回到下一条指令 |
陷阱 | 有意的异常 | 同步 | 总是返回到下一条指令 |
故障 | 潜在可恢复的错误 | 异步 | 可能返回到当前指令 |
终止 | 不可恢复的错误 | 同步 | 不会返回 |
-
中断
- 异步的,是来自处理器外部的I / O设备的信号的结果
- 异常程序常常称为中断处理程序
-
陷阱和系统调用
- 有意的异常
- 在用户程序和内核之间提供了一个像过程一样的接口,叫做系统调用
-
故障
-
终止
-
进程控制
-
获取进程ID
#include <sys/types.h> #include <unistd.h> pid_t getpid(void); pid_t getppid(void);
返回值是一个类型为pid_t的整型,在Linux系统中在types.h被定义为int
-
创建和终止进程
程序员角度,进程所处的三种状态
-
运行 在CPU上执行,或者等待被内核调度
- 就绪态和运行态合并为一种状态
-
停止 进程的执行被挂起(suspended),且不会被调度。进程收到以下信号进程停止,直到收到SIGCOUT,进程才开始运行
- SIGSTOP
- SIGTSTP
- SIGTTIN
- SIGTTOU
-
终止 进程永远停止,
- 收到一个信号,该信号默认行为是终止进程
- 从主程序返回
- 调用exit函数
#include <stdlib.h> void exit(int status);
父进程通过调用fork函数创建一个新的进程
#include <sys/types.h> #include <unistd.h> pid_t fork(void);
子进程得到一个与父进程用户级虚拟地址空间相同(但是独立)一个副本,包括
- 数据段
- 代码段
- 堆
- 共享空间
- 用户栈
子进程还可以读写父进程中打开的任何文件。
父进程与子进程之间最大的区别是他们有不同的PID;
可以理解为fork函数被调用了两次,一次在父进程中,一次在子进程当中
在父进程中fork返回的是子进程的PID,在子进程fork返回0
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> void unix_error(char *msg) { fprintf(stderr, "%s:%s\n", msg, strerror(errno)); exit(0); } pid_t Fork(void) { pid_t pid; if ((pid = fork()) < 0) unix_error((char *)"Fork error"); return pid; } int main(int argv, char *argc[]) { pid_t pid; int x = 1; pid = Fork(); //父进程与子进程是基本相同而且独立的程序,这里if父进程进不去,而子进程可以进去 //可以共享父进程打开的文件 if (pid == 0) { printf("child :x=%d\n", ++x); exit(0); } printf("parent :x=%d\n", --x); exit(0); }
-
-