xv6-util-sleep

sleep

实现一个UNIXsleep程序,要求使用sleep系统调用。

  • xv6 book 第一章
  • user/下有不少可以参考的程序
  • 如果用户没有参数,则打印错误信息
  • 用系统调用
  • 系统调用源代码在kernel/sysproc.c中可见
  • main函数应该使用exit(0)来正常推出
  • 将程序写入到Makefile的UPROGS中。

构建系统添加sleep

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
UPROGS=\
$U/_cat\
$U/_echo\
$U/_forktest\
$U/_grep\
$U/_init\
$U/_kill\
$U/_ln\
$U/_ls\
$U/_mkdir\
$U/_rm\
$U/_sh\
$U/_stressfs\
$U/_usertests\
$U/_grind\
$U/_wc\
$U/_zombie\
$U/_sleep\

sleep syscall的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// kernel/sysproc.c

uint64
sys_sleep(void)
{
int n;
uint ticks0;

if(argint(0, &n) < 0)
return -1;
acquire(&tickslock);
ticks0 = ticks;
while(ticks - ticks0 < n){
if(myproc()->killed){
release(&tickslock);
return -1;
}
sleep(&ticks, &tickslock);
}
release(&tickslock);
return 0;
}

其中,这里的sleep函数是一个在proc.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
// kernel/proc.c

// Atomically release lock and sleep on chan.
// Reacquires lock when awakened.
void
sleep(void *chan, struct spinlock *lk)
{
struct proc *p = myproc();

// Must acquire p->lock in order to
// change p->state and then call sched.
// Once we hold p->lock, we can be
// guaranteed that we won't miss any wakeup
// (wakeup locks p->lock),
// so it's okay to release lk.

acquire(&p->lock); //DOC: sleeplock1
release(lk);

// Go to sleep.
p->chan = chan;
p->state = SLEEPING;

sched();

// Tidy up.
p->chan = 0;

// Reacquire original lock.
release(&p->lock);
acquire(lk);
}

调度器、状态转移,这些概念应该在之后的课程中会涉及到。

自己实现的sleep.c

1
2
3
4
5
6
7
8
9
10
11
12
// user/sleep.c
#include "user.h"

int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: sleep <seconds>\n");
exit(-1);
}
int ticks = atoi(argv[1]);
sleep(ticks);
exit(0);
}

其中,他这里的uint还会出现一些编译错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In file included from user/sleep.c:1:
user/user.h:36:1: 错误:unknown type name ‘uint’; did you mean ‘int’?
36 | uint strlen(const char*);
| ^~~~
| int
user/user.h:37:26: 错误:unknown type name ‘uint’; did you mean ‘int’?
37 | void* memset(void*, int, uint);
| ^~~~
| int
user/user.h:38:1: 错误:函数声明中出现形参名却未指定类型 [-Werror]
38 | void* malloc(uint);
| ^~~~
user/user.h:41:40: 错误:unknown type name ‘uint’; did you mean ‘int’?
41 | int memcmp(const void *, const void *, uint);
| ^~~~
| int
user/user.h:42:36: 错误:unknown type name ‘uint’; did you mean ‘int’?
42 | void *memcpy(void *, const void *, uint);
| ^~~~
| int
cc1:所有的警告都被当作是错误

我在user/user.h中加了一个类型定义,来解决这个编译错误

然后再次make qemu就可以了。