Lecture 3. Thread & Process
- Why threads?
Kubi 提出了 MTAO 的概念(他自己造出来的词儿,Multiple things at once),同时做多件事。
因为需要线程去实现 MTAO。 - parallelism & concurrently
Multiprocessing 是 parallelism,Multiprogramming 不是 parallelism,他们都是 concurrently。 - syscalls
上图系统调用示意图。
疑问:为什么我们没有见过 syscall,这是因为往往 syscall 被隐藏在我们运行的语言的函数接口之下。这是因为在不同的操作系统上,syscall 是不同的,因此为了同一语言在不同操作系统上的运行,采用了这种隐藏的方式。
然而 syscalls 是有一个子集被标准化了的,这个子集称为 POSIX syscall interface,这一组 syscalls 在大部分系统上以同名实现。 - Threads State
信息共享情况如图 - Execution Stack
这个图很直观的展示了在函数递归的过程中,运行时堆栈会保存的信息,首先是参数,然后是临时变量(如果有),还有 ret,ret 表示的是结束调用后需要执行的下一条指令的位置。
上图是同一进程中不同线程的运行时堆栈的内存布局。
这涉及到一些有趣的问题:当一个栈增长得过长,将会搞乱另一个栈。
因此为此设立了 Guard Page,当栈触及这个页面的时候会陷入内核,并且决定是应该让栈获得更大的内存,抑或是终止线程,Kubi 说后面的课程会提到。 - Threads Race
多线程竞争资源,指令交错执行,老生常谈 - 一些和阻止多线程错误执行相关的概念
同步:协调多线程并让其正确执行的手段,通常于线程间共享的数据有关
互斥:同时只有线程作某件特定的事情,属于一种同步手段
Critical Section:同时只有一个 Thread 执行 Critical Section 的代码,Java 中可以使用 Synchronization 关键字来制作一段拥有这种功能的代码
锁:用来使某个对象同时只有一个 Thread 可以访问,属于一种互斥手段 - pthread(POSIX Thread)
pthread_create,创建线程
pthread_exit,退出线程
pthread_join,等待某个线程结束
pthread_mutex_init,创建锁
pthread_mutex_lock,阻塞式地获取锁
pthread_mutex_unlock,释放锁 - Process Create
每个进程都由其他进程创建。
宇宙大爆炸:在内核启动前,会有一个进程作为参数放入内核,这通常被称为 init 进程,然后 init 进程作为整个进程树的树根存在。 - PV operation for mutex
使用 PV(down/up) 操作来实现锁和 pthread_join(区别在于不同的阻塞位置和信号量的初始值)。
P 操作会等待信号量变为正数时给信号量 -1,V 操作会给信号量 +1,并告诉一个 P 操作停止等待 - Proccess APIs
exit,终止进程,进程正常 return 0 未调用 exit 时,OS 会自动为该进程调用 exit(0)
fork,开启子进程,对于父进程,返回子进程的 pid,对于子进程,返回 0。子进程会复制父进程的地址空间,并在新的地址空间中从同样的位置开始运行,子进程只会运行调用 fork 的 thread,其他所有的 threads 在子进程中会被终止
exec,没听懂,说是用来复制父进程的地址空间,然后把原来的副本全部删除,并在新的地址空间中运行的意思
wait,等待子进程运行完毕,并在参数中返回其 exit 的结果
sigaction,信号,有固定的信号表(例如 SIGINT 表示 Ctrl-C),也可以实现定制化的信号调用函数