park()可以让调用线程休眠 unpark(tid)可以唤醒tid标识的线程 setpark()可以使线程从park直接返回(其他线程调用unpark后) Linux系统里提供futex实现类似机制 为什么我们需要条件变量 void* child(void* arg){ printf("child\n"); // XXX how to indicate we are done? return NULL; } int main(int argc, char* argv[]){ printf("parent: begin\n"); pthread_t c; …
一、并发计数器 一个简单的计数器 typedef struct counter_t{ int value; } counter_t; void init(counter_t* c){ c->value = 0; } void increment(counter_t* c){ c->value++; } void decrement(counter_t* c){ c->value--; } int get(counter_t* c){ int rc = c->value; return rc; } 哪些地方需要加锁? 一种加锁方法:(全局都加上锁) typedef …
密码课乱写的笔记。 1. Fermat 方法(|p-q|较小) 由 $$ \frac{(p + q)^2}{4} - n = \frac{(p - q)^2}{4} - pq $$如果 $|p - q|$ 小,则 $$ \frac{(p - q)^2}{4} \text{也小,因此} \frac{(p + q)^2}{4} \text{稍大于} n, \frac{(p + q)}{2}\text{稍大于} \sqrt{n} $$可得 $n$ 的如下分解步骤:
一、锁的基本思想 通过加锁来保证临界区的原子性 lock_t mutex; ... lock(&mutex); // 获取锁,如果已被占用, 则等待,直到获得锁为止 balance = balance + 1; unlock(&mutex); // 释放锁 如何评价锁的实现 有效性:只有一个线程能拿到锁 公平性:所有线程都有机会拿到锁 不会出现饿死情况 性能:时间开销小 锁的实现一般要使用某种特 殊硬件指令,但也可以不用
问题:进程并发 // ... existing code ... int sum1 = 0, sum2 = 0; void p1() { int i, tmp = 0; for (i = 1; i <= 100; i++) tmp += i; sum1 += tmp; } void p2() { int i, tmp = 0; for (i = 101; i <= 200; i++) tmp += i; sum2 += tmp; } void p3() { printf("sum: %d\n", sum1 + sum2); } int main() { pid_t …
问题:放宽假设 当虚拟地址空间大于物理内存大小时,如何超越物理内存进行存储? 一、“虚拟内存” 1. 基本原理 OS的存储是分层级(hierarchy)的 越上层的存储越快 越底层的存储空间越大 time-space trade-off OS利用大而慢的设备,透明的提供巨大虚拟地址空间的假象
问题:页表很大 32位地址空间(4GB),带有4KB的页:20位的VPN,12位的offset 单个页表大小: $4 MB= 2^{20} entries * 4 Bytes$ 方案1:采用更大的页 32位地址空间(4GB),带有16KB的页 单个页表大小 $=\frac{2^{32}}{2^{14}} *4 B = 1 MB$ 问题:线性页表 为一个进程的整个地址空间提供一个线性页表 大量页表项是无效的!
一、“分页”地址转换 1. 分页基本原理 分页(paging)是将地址空间划分成固定大小的分片单元, 称为页/页面(page) 相对应的,物理内存同样也要分为相同大小的单元, 叫做页帧(page frame)
多图警告。 上一章空间管理的问题 大量的空闲(free)空间 - 这些空闲空间实实在在的占用了物理内存 必须为进程的整个虚拟地址空间分配 连续的物理内存 - 会导致什么问题? 一、“分段”地址转换 1. 基本原理 段是虚拟地址空间中的一个连续片段 代码段、栈段、堆段 对于每个段来说,都有它的基址和界限 只需以段为单位,给进程分配连续物理内存 物理地址 = 段基址 + 段内偏移 (段内偏移≠虚拟地址)
进程调度的概念 内核决定将CPU分配给某个就绪进程的过程 选择一个就绪的进程 调度指标 调度算法(策略) 进程切换 进程执行现场的切换(回顾进程) 一、进程调度的时机 非抢占式/协作式(Non-preemptive) 当一个进程从运行态切换到阻塞态(例如 发生I/O请求) 当一个进程终止 抢占式(Preemptive) 当一个进程从运行态切换到就绪态(例如 出现时钟中断) 当一个进程从阻塞态切换到就绪态(例如 I/O完成) 非抢占式情况下必须等待进程完成再考虑下一 步调度,抢占式可以在进程执行时切换进