oslab_2任务解析(sleep primes sixfive find&exec)
sleep
两个重要参数
argc——参数的个数
argv——参数的数组
示例:
$ find . 123 -exec echo
此时argc = 5
argv[0]=“find”
argv[1]=“.”
argv[2]=“123”
argv[3]=“-exec”
argv[4]=“echo”
argv[5]=“0” ——结束符
atoi
作用是将字符串格式的命令行参数转为整数
- 遇到任何非数字字符,循环立刻停止,返回已经累积的值
- 开头就是非数字 → 一次循环都不进 → 返回 0
*pasue的实现流程
pasue函数在user.h声明,在usys.S中切换到内核态指向sys_pause()函数
通过时钟中断来“计数”,每0.1s执行clockintr()使得ticks+1,并且进行一次wakeup
wakeup后进程的state被设置为RUNNABLE
sleep函数就是把进程的state改为SLEEPING后使用sched()从当前进程切换到scheduler,使得当前进程处于sleep状态
第一,“处于 sleep 状态”——被动变 RUNNABLE,不是永久睡眠。
进程不是“睡着了就一直睡到时间到”,而是进入排队状态,每 0.1 秒被 wakeup 拍一下、重新排一次队。所以准确说是:反复“出队 → 检查 → 再排队”的循环
第二,scheduler 只挑 RUNNABLE 的:
if(p->state == RUNNABLE) {
p->state = RUNNING;
c->proc = p;
swtch(&c->context, &p->context);
SLEEPING 的进程会被这个 if 直接跳过。 这就是“睡眠”的实际效果——不被调度。state = SLEEPING 是一个“请不要调度我”的标记。

primes
p[0]/p[1] 的完整含义是
p[0] = 3 ──► ofile[3] ──► struct file{ type:FD_PIPE, readable:1, writable:0, pipe: ─┐}
│
p[1] = 4 ──► ofile[4] ──► struct file{ type:FD_PIPE, readable:0, writable:1, pipe: ─┤
▼
┌──────────────────┐
│ struct pipe │
│ data[512] │
│ nread / nwrite │
│ readopen=1 │
│ writeopen=1 │
└──────────────────┘
两个 fd 指向同一个内核 struct pipe 对象。 通信成立。
在 main 刚启动、fd编号只有 0/1/2 被占用
main: 写 2,3,4,…,40 到管道0,close(写端) ↓ sieve(rfd=3) ← 第一级,筛 2 ├─ read → 2 ├─ print “prime 2” ├─ pipe() → 新管道1 (p[0]=5, p[1]=6) ├─ fork() │ ├─ 子: close(3), close(6), sieve(5) ← 第二级,筛 3 │ └─ 父: close(5) ├─ 父循环: 读 3,4,5,…,40 │ ├─ 3%2≠0 → write(6, 3) ┐ │ ├─ 4%2=0 → 丢弃 │ 奇数流入下游 │ ├─ 5%2≠0 → write(6, 5) │ │ └─ … 39%2≠0 → write(6,39) ┘ ├─ read 返回 0(上游写端已关)→ 跳出循环 ├─ close(3), close(6) ← ★ 发 EOF 给下一级 ├─ wait(0) ← 等子进程跑完 └─ return → main exit(0)
子进程(筛 3): ├─ read(5) → 3, print “prime 3” ├─ pipe() → 管道2, fork() │ ├─ 孙: close(5), close(p[1]), sieve(p[0]) │ └─ 子: close(p[0]) ├─ 读 3,5,7,9,…,39 │ ├─ 3%3=0 → 丢弃 │ ├─ 5%3≠0 → write → 下游 │ └─ … ├─ close(5), close(写端), wait(0) └─ return → 回到父进程的 wait(0),子进程结束
sixfive
较简单,过!
find&exec
分为find和exec两个阶段
find通过递归找target文件是否存在,重点是T_DIR这个case
while(read(fd, &de, sizeof(de)) == sizeof(de))实现依次读这个目录下的文件夹/文件
exec通过在”-exec“后构建一个新的argv参数数组来执行其后面的命令: 构造 argv = g_cmd[0..n-1] + path + 0. g_cmd
是-exec后面的命令部分