进程、线程、协程都是实现任务级并行/并发的手段。

协程(coroutine)

Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed. —— Wikipedia

就tmd是允许执行被挂起与被恢复的子程序。

令人意想不到的是,历史上最早出现的居然是协程。

协程能进行并发,如果调度器允许,也可以用来并行。

原始协程

在非常非常老的OS上(Windows 3.5之前?),多个任务的并发是通过每个任务在自己等待IO时主动放弃CPU来进行的。

这就是一种非常原始的协程。

有栈协程

有栈协程不过是把“线程”的上下文切换工作从内核控制变为了由用户代码自行控制,也就是说,协程有自己的栈。

无栈协程

无栈协程没有栈,他只是把栈帧放在了调用方的栈中。

C实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
#include <stdbool.h>

#define COROUTINE_COUNT 10

int async_function_state[COROUTINE_COUNT + 1];
jmp_buf async_function_point[COROUTINE_COUNT + 1];
jmp_buf start_function_point;

void states() {
for (int i = 1; i <= COROUTINE_COUNT; ++i) {
printf("%d ", async_function_state[i]);
}
printf("\n");
}

void schedule(int this_id) {
states();
bool all_finished = true;
for (int i = 1; i <= COROUTINE_COUNT; ++i) {
if (async_function_state[i] != -1) {
all_finished = false;
break;
}
}
if (all_finished) {
printf("All finished\n");
return;
}
int next_id = random() % COROUTINE_COUNT + 1;
while (async_function_state[next_id] == -1) {
next_id = random() % COROUTINE_COUNT + 1;
}
printf("%d going down, %d coming up\n", this_id, next_id);
longjmp(async_function_point[next_id], next_id);
}

void async_function(int id) {
int i = setjmp(async_function_point[id]);
if (async_function_state[COROUTINE_COUNT] == 0) {
++async_function_state[id];
printf("Coroutine %d started!\n", id);
longjmp(start_function_point, id);
}
id = i;
switch (async_function_state[id]) {
case 1:
printf("Just entered coroutine %d!\n", id);
++async_function_state[id];
schedule(id);
case 2:
printf("Continue %d!\n", id);
++async_function_state[id];
schedule(id);
case 3:
printf("%d end!\n", id);
async_function_state[id] = -1;
schedule(id);
}
}

int main() {
volatile int id = 0;
if (setjmp(start_function_point) != 10) {
async_function(++id);
}
schedule(1);
return 0;
}

(这里牵扯到一个叫Duff’s device的C编程“技巧”,可以搜一下,保证辣眼睛)

进程

In computing, a process is the instance of a computer program that is being executed by one or many threads. It contains the program code and its activity.

操作系统课上该讲的都讲了,我就不多BB了。

线程

In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler), which is typically a part of the operating system.[1]#cite_note-1)

同上

思考题

RT-Thread等单片机操作系统支持的,在Cortex-m3这类没有MPU或MMU的板子上运行的“一段程序”是线程还是进程?

他确实是“instance) of a computer program that is being executed by one or many threads”,但他没有独立的地址空间,也的确是“the smallest sequence of programmed instructions that can be managed independently by a scheduler)”。