Compare commits
2 Commits
8557145281
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 64e47032d4 | |||
| a623e36b6f |
127
UCB-CS162/L03-Processes-and-Threads.md
Normal file
127
UCB-CS162/L03-Processes-and-Threads.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Processes and Threads
|
||||
|
||||
## Motivation for threads 为什么我们需要线程
|
||||
|
||||
- 操作系统必须支持多个任务同时运行。例如,进程、终端或系统维护。
|
||||
- 操作系统必须支持多个连接同时运行。例如,多用户、Web连接等。
|
||||
- 进程必须能够同时执行多个任务。例如,一个游戏必须同时有图形、声音与运算逻辑等。
|
||||
- 操作系统必须同时访问多个硬件,或者至少看起来像是同时访问。你不会希望动鼠标、按键盘时,系统不能访问网络或磁盘。
|
||||
|
||||
一些定义:
|
||||
|
||||
- Multi-Processing:多个 CPU(核心)
|
||||
- Multi-Programming:多个作业/进程
|
||||
- Multi-Threading:多个线程/进程
|
||||
|
||||
### Concurrency 并发
|
||||
|
||||
**并发**运行两个线程意味着什么?
|
||||
|
||||
- 调度器可以自由地,以任意顺序和交错方式,运行线程
|
||||
- 线程可能会运行至完成,或者以大块或小块的时间片运行
|
||||
|
||||

|
||||
|
||||
### Computes that never finish 永远无法完成的计算
|
||||
|
||||
想象如下代码,其中ComputePi()会尝试计算π的最后一位,并将计算过程写入文件pi.txt。
|
||||
|
||||
```C
|
||||
main() {
|
||||
ComputePI("pi.txt");
|
||||
PrintClassList("classlist.txt");
|
||||
}
|
||||
```
|
||||
|
||||
这个例子中,显然ComputePi是个不可能完成的函数。因此我们完全没有办法print ClassList!程序也无法停止,除非你Ctrl-C或者关闭电脑。
|
||||
|
||||
但是使用线程,我们可以这么做:
|
||||
|
||||
```C
|
||||
main() {
|
||||
create_thread(ComputePI, "pi.txt");
|
||||
create_thread(PrintClassList, "classlist.txt");
|
||||
}
|
||||
```
|
||||
|
||||
这样,即便ComputePI永远无法完成,我们也可以得到ClassList。
|
||||
|
||||
### IO / Compute Overlap
|
||||
|
||||
这是一个各种操作的时间表:
|
||||
|
||||
| Operation | Time |
|
||||
| :--- | :--- |
|
||||
| L1 cache reference | 0.5 ns |
|
||||
| Branch mis-predict | 5 ns |
|
||||
| L2 cache reference | 7 ns |
|
||||
| Mutex lock/unlock | 25 ns |
|
||||
| Main memory reference | 100 ns |
|
||||
| Compress 1K bytes with Zippy | 3,000 ns |
|
||||
| Send 2K bytes over 1 Gbps network | 20,000 ns |
|
||||
| Read 1 MB sequentially from DDR2 memory | 250,000 ns |
|
||||
| Round trip within same datacenter | 500,000 ns |
|
||||
| Disk seek on HDD | 10,000,000 ns |
|
||||
| Read 1 MB sequentially from HDD disk | 20,000,000 ns |
|
||||
| Send packet CA->Netherlands->CA | 150,000,000 ns |
|
||||
|
||||
Disk Seek(硬盘寻址)等操作显然需要很久,比如10ms。我们显然不希望CPU的一个核心等待这么久,不做任何计算。
|
||||
|
||||
## Introduction to threads 线程简介
|
||||
|
||||
线程有三个状态。如下:
|
||||
|
||||
- Running 运行态: 线程正在使用CPU的时间片
|
||||
- Ready 就绪态: 线程准备好运行了,但还没有上CPU
|
||||
- Blocked 阻塞态: 线程不能继续运行
|
||||
|
||||
我们可以基于此设计调度器。例如,如果两个线程都不需要IO,它们很可能会轮流使用同一个CPU核心:
|
||||

|
||||
|
||||
但是如果其中一个线程需要执行IO操作,那么它就会被阻塞,另一个线程就可以继续使用CPU核心:
|
||||

|
||||
|
||||
注: Blocked状态不会直接转为Running状态,必须先转为Ready状态。
|
||||
|
||||
### How to manage threads 如何管理线程
|
||||
|
||||
一个程序默认就含有一个线程。如果想要创建其他线程,我们必须使用一次System Call。
|
||||
|
||||
在C语言中,使用```pthread_create()```函数来创建线程。
|
||||
|
||||
```C
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine)(void*), void *arg);
|
||||
```
|
||||
|
||||
- 创建线程,并以 `arg` 为唯一参数执行 `start_routine`。
|
||||
- `return` 相当于隐式调用 `pthread_exit`。
|
||||
|
||||
```C
|
||||
void pthread_exit(void *value_ptr);
|
||||
```
|
||||
|
||||
- 终止线程,并使 `value_ptr` 对任何成功的 `join` 操作可用
|
||||
|
||||
```C
|
||||
int pthread_join(pthread_t thread, void **value_ptr);
|
||||
```
|
||||
|
||||
- 挂起调用线程的执行,直到目标线程终止。
|
||||
- 返回时,若 `value_ptr` 非 `NULL`,则终止线程传递给 `pthread_exit()` 的值将存储在 `value_ptr` 指向的位置。
|
||||
|
||||
#### `void *(*start_routine)(void*)`是什么玩意?
|
||||
|
||||
我们从内向外看这个东西。
|
||||
`*start_routine` 是一个函数指针,指向一个函数,这个函数接受一个 `void*` 类型的参数,并返回一个 `void*` 类型的值。
|
||||
|
||||
## System Calls
|
||||
|
||||
System Call 接口隔开了用户程序与操作系统内核。
|
||||
这使得系统设计看起来像一个沙漏,而System Call正式沙漏中间最窄的地方,
|
||||
如图所示:
|
||||

|
||||
你会注意到System Call之上,用户程序之下还有一层Portable OS Library。这个库允许程序员使用同一套API来编写程序。
|
||||
|
||||
- C程序猿们会使用`libc`,提供很多以某种方式包装的系统调用。
|
||||
|
||||
BIN
UCB-CS162/images/L03-MultiProcessing-vs-MultiProgramming.png
Normal file
BIN
UCB-CS162/images/L03-MultiProcessing-vs-MultiProgramming.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 233 KiB |
BIN
UCB-CS162/images/L03-System-Call-In-OS.png
Normal file
BIN
UCB-CS162/images/L03-System-Call-In-OS.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 827 KiB |
BIN
UCB-CS162/images/L03-Thread-Scheduling-With-IO.png
Normal file
BIN
UCB-CS162/images/L03-Thread-Scheduling-With-IO.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
BIN
UCB-CS162/images/L03-Thread-Scheduling-Without-IO.png
Normal file
BIN
UCB-CS162/images/L03-Thread-Scheduling-Without-IO.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
Reference in New Issue
Block a user