This type of trade-off is common in systems; you can’t have your cake and eat it too4
程序运行时发生什么?
一个正在运行的程序会做一件非常简单的事情:执行指令。处理器从内存中获取(fetch)一条指令,对其进行解码(decode)(弄清楚这是哪条指令),然后执行(execute)它(做它应该做的事情,如两个数相加、访问内存、检查条件、跳转到函数等)
2.1 虚拟化 CPU
操作系统负责提供一种假象 illusion, 将单个 CPU 转换为看似无限多的 CPU,即 virtualizing the CPU
2.2 虚拟化内存
内存就是一个字节数组,要 read 内存,就必须指定一个 address, 才能访问那里的数据,要写入 write 或 更新 update,需指定写入给定地址的数据
2.3 并发 concurrency
You can think of a thread as a function running whithin the same memory space as other functions, with more than one of them active at a time. 你可以将线程看成与其他函数在同一内存空间中运行的函数,并且每次都有多个线程处于活动状态
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "common_threads.h"
volatile int counter = 0;
int loops;
void *worker(void *arg) {
int i;
for (i = 0; i < loops; i++) {
counter++;
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: threads <value>\\n");
exit(1);
}
loops = atoi(argv[1]);
pthread_t p1, p2;
printf("Initial value: %d\\n", counter);
Pthread_create(&p1, NULL, worker, NULL);
Pthread_create(&p2, NULL, worker, NULL);
Pthread_join(p1, NULL);
printf("Final value : %d\\n", counter);
return 0;
}
// ./thread 100000
// Initial value : 0
// Final value : 143012 // huh??
// ./thread 100000
// Initial value : 0
// Final value : 137298 // what the??
In this example, each thread starts running in a routine called worker(), in which it simply increments a counter in a loop for loops
number of times.
上面的程序中的关键部分是增加共享计数器的地方,它需要3条指令:一条将计数器的值从内存加载到寄存器,一条将其递增,另一条将其保存回内存。因为这3条指令并不是以原子方式(atomically)执行(所有的指令一次性执行)的,所以奇怪的事情可能会发生
2.4 持久性
一个进行 I/O 的程序: create a file that contains the string "hello world"