《信息安全系统设计基础》第13周学习总结
教材学习内容
并发编程
1、程序级并发——进程
2、函数级并发——线程
三种基本的构造并发程序的方法:
1、进程:每个逻辑控制流是一个进程,由内核进行调度,进程有独立的虚拟地址空间
2、I/O多路复用:逻辑流被模型化为状态机,所有流共享同一个地址空间
3、线程:运行在单一进程上下文中的逻辑流,由内核进行调度,共享同一个虚拟地址空间
基于进程的并发编程
-
构造并发程序最简单的方法——用进程。常用函数:fork,exec,waitpid
-
优点:防止虚拟存储器被错误覆盖
-
缺点:开销有时会很高,共享状态信息才需要IPC机制
需要注意的事情:
1、父子进程之间共享文件表,但是不共享用户地址空间
2、必须要包括一个SIGCHLD处理程序来回收僵死子进程的资源
基于I/O多路复用的并发编程
-
使用select函数要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。
-
select函数处理类型为fd_set的集合,即描述符集合。
-
当且仅当一个从该描述符读取一个字节的请求不会阻塞时,描述符k表示准备好可以读了
-
必须在每次调用select时都更新读集合
基于线程的并发编程
-
线程:就是运行在进程上下文中的逻辑流。
-
线程由内核自动调度。每个线程都有它自己的线程上下文:
一个唯一的整数线程ID——TID
- 栈
- 栈指针
- 程序计数器
- 通用目的寄存器
- 条件码
线程执行模型
一、线程执行模型
1.主线程,进程中第一个运行的线程
2.对等线程,某时刻主线程创建,之后两个线程并发运行每个对等线程都能读写相同的共享数据。
3.主线程切换到对等线程
Posix线程
- Posix线程是C程序中处理线程的一个标准接口。基本用法是:
- 线程的代码和本地数据被封装在一个线程例程中
- 每个线程例程都以一个通用指针为输入,并返回一个通用指针。
线程
1、创建线程:pthread_create函数,返回时参数tid包含新创建线程的ID
2、 查看线程ID:pthread_self函数,返回调用者的线程ID(TID)
3、终止线程
1.隐式终止:顶层的线程例程返回
2.显示终止:调用pthread_exit函数(如果主线程调用,会先等待所有其他对等线程终止,再终止主线程和整个进程)返回值为pthread_return
3.某个对等线程调用Unix的exit函数,会终止进程与其相关线程
4.另一个对等线程通过以当前线程ID作为参数调用pthread_cancle来终止当前线程
4、 回收已终止线程的资源
-
pthread_join函数等待其他线程终止
-
这个函数会阻塞,知道线程tid终止,将线程例程返回的(void*)指针赋值为thread_return指向的位置,然后回收已终止线程占用的所有存储器资源
5、分离线程
- 任何一个时间点上,线程是可结合的或者是分离的。
- 一个可结合的线程能够被其他线程收回其资源和杀死;一个可分离的线程是不能被其他线程回收或杀死的。它的存储器资源在它终止时有系统自动释放。
- 默认情况下,线程被创建成可结合的,为了避免存储器漏洞,每个可集合的线程都应该要么被其他进程显式的回收,要么通过调用pthread _detach函数被分离。
6、初始化线程
- pthread _once函数允许初始化与线程例程相关的状态。
- once _control变量是一个全局或者静态变量,总是被初始化为PTHREAD _ONCE _INIT
多线程程序中的变量共享
-
线程存储器模型
每个线程和其他线程一起共享进程上下文的剩余部分。包括整个用户虚拟地址空间,是由只读文本、读/写数据、堆以及所有的共享库代码和数据区域组成的。线程也共享同样的打开文件的集合。
任何线程都可以访问共享虚拟存储器的任意位置。寄存器是从不共享的,而虚拟存储器总是共享的。 -
将变量映射到存储器
- 全局变量:虚拟存储器的读/写区域只会包含每个全局变量的一个实例。
- 本地自动变量:定义在函数内部但没有static属性的变量。
- 本地静态变量:定义在函数内部并有static属性的变量。
用信号量同步线程
- 共享变量引入了同步错误的可能性。
- 线程i的循环代码分解为五部分:
1.Hi:在循环头部的指令块
2.Li:加载共享变量cnt到寄存器%eax的指令,%eax表示线程i中的寄存器%eax的值
3.Ui:更新(增加)%eax的指令
4.Si:将%eaxi的更新值存回到共享变量cnt的指令
5.Ti:循环尾部的指令块。
进度图
- 进度图将指令执行模式化为从一种状态到另一种状态的转换。转换被表示为一条从一点到相邻点的有向边。合法的转换是向右或者向上。
- 临界区:对于线程i,操作共享变量cnt内容的指令构成了一个临界区。
- 互斥的访问:确保每个线程在执行它的临界区中的指令时,拥有对共享变量的互斥的访问。
信号量
- 当有多个线程在等待同一个信号量时,你不能预测V操作要重启哪一个线程。
- 信号量不变性:一个正在运行的程序绝不能进入这样一种状态,也就是一个正确初始化了的信号量有一个负值。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 3500行 | 30篇 | 400小时 | |
第一周 | 40/40 | 1/1 | 20/20 | |
第二周 | 30/70 | 1/2 | 30/50 | |
第三周 | 21/91 | 1/3 | 28/78 | |
第五周 | 131/222 | 1/4 | 20/98 | |
第六周 | 32/254 | 1/5 | 21/119 | |
第七周 | 200/454 | 1/5 | 21/119 | |
第八周 | 0/454 | 2/7 | 10/129 | |
第九周 | 84/538 | 2/9 | 15/144 | |
第10周 | 441/979 | 2/11 | 10/154 | |
第11周 | 460/1439 | 2/13 | 20/174 | |
第12周 | 300/1739 | 2/15 | 20/194 | |
第13周 | 301/2040 | 1/16 | 19/213 |