第7章 第006章_死锁状态.txt

# Chapter 006: Deadlock

# Status: Timeline 1974.5.12

# Location: Bell Labs, Murray Hill

>>> Timeline Jump Complete

>>> Current Location: Bell Labs, 1974

>>> Mission: Fix critical deadlock in Unix V5

>>> Warning: Process scheduling system compromised

>>> Status: Initializing environment...

当世界重新清晰时,我发现自己站在一台PDP-11/45前。显示器上滚动着一连串错误信息:

PANIC: System freeze

PANIC: Process table full

PANIC: Resource unavailable

...

"整个系统都卡住了,"Ken Thompson揉着太阳穴说,"这是这周第三次了。"

我快速浏览着系统日志。这是Unix V5版本,第一个被广泛使用的Unix系统。如果在这个版本中存在严重的死锁问题,那将影响到后来所有的Unix分支。

struct proc {

char p_stat; /* 进程状态 */

char p_flag; /* 标志位 */

char p_pri; /* 优先级 */

char p_sig; /* 信号 */

char p_uid; /* 用户ID */

char p_time; /* 运行时间 */

char p_cpu; /* CPU使用率 */

char p_nice; /* nice值 */

int p_ttyp; /* 控制终端 */

int p_pid; /* 进程ID */

int p_ppid; /* 父进程ID */

int p_addr; /* 数据段地址 */

int p_size; /* 数据段大小 */

int *p_wchan; /* 等待通道 */

};

"让我看看进程调度代码。"我说。

void sched() {

struct proc *p;

int c;

while(1) {

c = -1;

for(p = &proc[0]; p < &proc[NPROC]; p ) {

if(p->p_stat == SRUN && p->p_flag == 0) {

c = p->p_cpu & 0377;

if(c > maxpri) {

maxpri = c;

runproc = p;

}

}

}

if(c < 0) {

// 没有可运行的进程

idle();

continue;

}

swtch();

}

}

"问题在这里,"我指着屏幕说,"系统没有正确处理资源竞争。"

我开始分析死锁发生的场景:

1. 进程A持有资源X,等待资源Y

2. 进程B持有资源Y,等待资源X

3. 两个进程互相等待,形成死锁

"我们需要实现死锁检测和预防机制。"我说着,开始修改代码:

struct resource {

int r_type; /* 资源类型 */

int r_id; /* 资源ID */

int r_owner; /* 当前持有者 */

int r_waiters; /* 等待队列 */

};

struct proc {

// ... 原有字段 ...

int p_resources[NRES]; /* 持有的资源 */

int p_waiting; /* 等待的资源 */

};

int allocate_resource(struct proc *p, struct resource *r) {

if(r->r_owner != 0) {

// 资源被占用,检查是否会造成死锁

if(would_deadlock(p, r)) {

return 0; // 拒绝分配

}

p->p_waiting = r->r_id;

sleep(p);

return 1;

}

r->r_owner = p->p_pid;

p->p_resources[r->r_id] = 1;

return 1;

}

int would_deadlock(struct proc *p, struct resource *r) {

struct proc *owner = &proc[r->r_owner];

int visited[NPROC] = {0};

// 检查是否形成等待环

return check_cycle(p, owner, visited);

}

int check_cycle(struct proc *start, struct proc *current, int *visited) {

if(current == start) {

return 1; // 发现循环

}

if(visited[current->p_pid]) {

return 0;

}

visited[current->p_pid] = 1;

if(current->p_waiting) {

struct resource *r = &resources[current->p_waiting];

if(r->r_owner) {

return check_cycle(start, &proc[r->r_owner], visited);

}

}

return 0;

}

"这个修改增加了资源分配表和死锁检测算法,"我解释道,"在分配资源之前,系统会检查是否会导致死锁。如果检测到潜在的死锁,就拒绝分配资源。"

Ken Thompson认真地看着代码:"但这会不会影响性能?"

"性能确实会有一些影响,"我承认道,"但比起系统完全死锁要好得多。而且我们可以优化检测算法..."

为了验证修改的效果,我编写了一个测试程序:

void test_deadlock() {

int pid1, pid2;

pid1 = fork();

if(pid1 == 0) {

// 子进程1

get_resource(1);

sleep(1);

get_resource(2);

exit(0);

}

pid2 = fork();

if(pid2 == 0) {

// 子进程2

get_resource(2);

sleep(1);

get_resource(1);

exit(0);

}

}

>>> Running deadlock test...

>>> Process 1: Acquired resource 1

>>> Process 2: Acquired resource 2

>>> Process 1: Waiting for resource 2

>>> Process 2: Resource 1 denied (deadlock prevention)

>>> Test passed: No deadlock occurred

"系统成功避免了死锁!"我说。但就在这时,熟悉的眩晕感又来了。

>>> Mission Completed

>>> Timeline Stable

>>> Bug Fixed: Process Deadlock Prevention

>>> Historical Impact: Significant

>>> Note: Resource Management Model Established

>>> Preparing for next jump...

在视线模糊之前,我看到Ken Thompson正在他的笔记本上记录这些改动。这些代码将成为后来Unix系统进程调度和资源管理的基础。

死锁问题,操作系统设计中最经典的难题之一。通过这次修复,我不仅帮助Unix避免了一个严重的问题,也为后来的操作系统提供了重要的参考。

这让我想起了那句老话:如果说我能看得更远,那是因为我站在巨人的肩膀上。只是这一次,我有幸帮助巨人避免了一次跌倒。

# End of Chapter 006

# Next Timeline Loading...

梦远书城已将原网页转码以便移动设备浏览

本站仅提供资源搜索服务,不存放任何实质内容。如有侵权内容请联系搜狗,源资源删除后本站的链接将自动失效。

推荐阅读

仓鼠后备军

小欢喜:成长系统

今日有囍

我靠线人系统在刑侦文里当热心市民

我的恋爱指数要满仓

< 上一章 目录 下一章 >
×
量子纠缠:我,林深,在代码里修改世界线
连载中无黯001 /