├── .gitignore
├── lab1
├── lab1.docx
├── lab1.pptx
├── README.md
├── setup.s
├── build.c
└── bootsect.s
├── lab2
├── Lab2.pptx
├── lab2.docx
├── iam.c
├── README.md
├── whoami.c
├── who.c
├── testlab2.sh
├── sys.h
├── Makefile
├── testlab2.c
├── system_call.s
└── unistd.h
├── lab3
├── lab3.docx
├── lab3.pptx
├── process-10.log
├── README.md
├── process-20.log
├── process.log
├── process.c
├── printk.c
├── fork.c
├── exit.c
├── main.c
├── system_call.s
├── sched.h
├── stat_log.py
└── sched.c
├── lab5
├── Lab5.pptx
├── Lab5 信号量的实现与应用.docx
├── README.md
├── sys.h
├── pc.c
├── Makefile
├── sem.c
├── bin.txt
├── system_call.s
└── unistd.h
├── lab7
├── Lab7.doc
├── lab7.pptx
├── read_write.c
├── tty_io.c
└── keyboard.S
├── lab6
├── 111
├── Lab6 地址映射与共享.docx
├── Lab6 —— 地址映射与共享.pptx
├── Makefile
├── shm.c
├── producer.c
├── consumer.c
├── sys.h
├── README.md
├── system_call.s
├── unistd.h
└── memory.c
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 |
--------------------------------------------------------------------------------
/lab1/lab1.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab1/lab1.docx
--------------------------------------------------------------------------------
/lab1/lab1.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab1/lab1.pptx
--------------------------------------------------------------------------------
/lab2/Lab2.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab2/Lab2.pptx
--------------------------------------------------------------------------------
/lab2/lab2.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab2/lab2.docx
--------------------------------------------------------------------------------
/lab3/lab3.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab3/lab3.docx
--------------------------------------------------------------------------------
/lab3/lab3.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab3/lab3.pptx
--------------------------------------------------------------------------------
/lab5/Lab5.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab5/Lab5.pptx
--------------------------------------------------------------------------------
/lab7/Lab7.doc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab7/Lab7.doc
--------------------------------------------------------------------------------
/lab7/lab7.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab7/lab7.pptx
--------------------------------------------------------------------------------
/lab6/Lab6 地址映射与共享.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab6/Lab6 地址映射与共享.docx
--------------------------------------------------------------------------------
/lab5/Lab5 信号量的实现与应用.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab5/Lab5 信号量的实现与应用.docx
--------------------------------------------------------------------------------
/lab6/Lab6 —— 地址映射与共享.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rccoder/HIT-OS-Lab/HEAD/lab6/Lab6 —— 地址映射与共享.pptx
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HIT-OS-Lab
2 | ### 哈工大操作系统实验
3 | **含报告,PPT,以及做实验过程中的一些小记录`README.md`**
4 |
5 |
6 | 说明:
7 | * 不保证所有的代码都正确,如果有问题,欢迎发送Pull Request.
8 |
9 | * 融合大量学长学姐的结晶完成!
10 |
--------------------------------------------------------------------------------
/lab5/README.md:
--------------------------------------------------------------------------------
1 | * 和Lab2的实现没有什么区别
2 |
3 | * 注意:
4 | + 自己实现pc.c,然后复制到linux0.11中使用
5 | + 自行编写sem.c, 修改markfile编译进去
6 | + sem.c里面用了一个`sem_t`的数据结构,需要在`unistd.h`里面定义
7 |
8 |
9 | * 难点就是编写sem.c和pc.c
10 |
11 |
--------------------------------------------------------------------------------
/lab2/iam.c:
--------------------------------------------------------------------------------
1 | #define __LIBRARY__
2 | #include
3 | #include
4 |
5 | _syscall1(int, iam, const char*, name);
6 |
7 | int main(int argc, char ** argv)
8 | {
9 | iam(argv[1]);
10 | return 0;
11 | }
12 |
--------------------------------------------------------------------------------
/lab2/README.md:
--------------------------------------------------------------------------------
1 | * include/linux/sys.h 仿照添加 两处
2 | * include/unistd.h 添加系统调用号
3 | * kernel/system_call.s 改变系统调用总数
4 | * kernel/who.c 写要实现的系统调用函数 需要include/asm/segment.h 帮助调用输入输出
5 | * kernel/Makefile 修改,让who.c和其他代码编译在一起
6 |
--------------------------------------------------------------------------------
/lab1/README.md:
--------------------------------------------------------------------------------
1 | * bootsect.s --- 改变字符串,如果长要改变前面的字符长度,不然显示不全
2 | * setup.s --- 复制bootsect.s,做相关的改动,大概如下:
3 | + 地址给对(bootsect.s里面写的是BOOTSEG)
4 | + 通过中断取到数据,存储下来
5 | + 提示信息模仿`loading system`输出
6 | + 最后用死循环,防止持续调用已经执行完的操作
7 | * build.c --- 默认输出有三个参数,做改变(第三个参数为none时直接返回)
8 |
--------------------------------------------------------------------------------
/lab2/whoami.c:
--------------------------------------------------------------------------------
1 | #define __LIBRARY__
2 | #include
3 | #include
4 | #include
5 |
6 | _syscall2(int, whoami, char*, name, unsigned int, size);
7 |
8 | int main(int argc, char ** argv)
9 | {
10 | char t[30];
11 | whoami(t, 30);
12 | printf("%s\n", t);
13 | return 0;
14 | }
15 |
--------------------------------------------------------------------------------
/lab3/process-10.log:
--------------------------------------------------------------------------------
1 | 1 N 48
2 | 1 J 48
3 | 0 J 48
4 | 1 R 48
5 | 2 N 49
6 | 2 J 49
7 | 1 W 49
8 | 2 R 49
9 | 3 N 63
10 | 3 J 64
11 | 2 E 68
12 | 1 J 68
13 | 1 R 68
14 | 4 N 68
15 | 4 J 68
16 | 1 W 69
17 | 3 R 69
18 | 3 W 74
19 | 4 R 74
20 | 5 N 106
21 | 5 J 107
22 | 4 W 107
23 | 5 R 107
24 | 4 J 109
25 | 5 E 110
26 | 4 R 110
27 | 4 W 115
28 | 0 R 115
29 | 4 J 491
30 | 4 R 491
31 | 4 W 491
32 | 0 R 491
33 | 4 J 521
34 | 4 R 521
35 | 4 W 521
36 | 0 R 521
37 | 4 J 566
38 | 4 R 566
39 | 4 W 566
40 | 0 R 566
41 | 4 J 608
42 | 4 R 608
43 | 4 W 608
44 | 0 R 608
45 | 4 J 999
46 | 4 R 999
47 | 4 W 999
48 | 0 R 999
49 | 4 J 1108
50 | 4 R 1108
51 | 4 W 1108
52 | 0 R 1108
53 | 4 J 1155
54 | 4 R 1156
55 | 4 W 1156
56 | 0 R 1156
57 | 4 J 2198
58 | 4 R 2198
59 | 6 N 2200
60 | 6 J 2200
61 | 4 W 2201
62 | 6 R 2201
63 |
--------------------------------------------------------------------------------
/lab2/who.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | char msg[24];
6 |
7 | int sys_iam(const char * name)
8 | {
9 | char tep[26];
10 | int i = 0;
11 | for(; i < 26; i++)
12 | {
13 | tep[i] = get_fs_byte(name+i);
14 | if(tep[i] == '\0') break;
15 | }
16 |
17 | if (i > 23) return -(EINVAL);
18 |
19 | strcpy(msg, tep);
20 | return i;
21 | }
22 |
23 | int sys_whoami(char * name, unsigned int size)
24 | {
25 | int len = 0;
26 | for (;msg[len] != '\0'; len++);
27 |
28 | if (len > size)
29 | {
30 | return -(EINVAL);
31 | }
32 |
33 | int i = 0;
34 | for(i = 0; i < size; i++)
35 | {
36 | put_fs_byte(msg[i], name+i);
37 | if(msg[i] == '\0') break;
38 | }
39 | return i;
40 | }
41 |
--------------------------------------------------------------------------------
/lab3/README.md:
--------------------------------------------------------------------------------
1 | * 按照给定的模板写process.c,主要写main函数创建进程,然后在Linux-0.11上编译测试运行结果
2 | * 在还没开始fork的时候,即进程0中进行log文件的打开,与文件描述符3相关联 --- init/main.c
3 | + 进程0和1的文件描述符肯定和log相关联
4 | + 理论上后面的进程都会继承1,但是后面会在/bin/sh重新初始化,所以只有0和1相关联
5 | * 写log文件
6 | + 和printk功能类似,代码放在 kernel/printk.c
7 | + 代码给出
8 | * 跟踪进程运动轨迹
9 | + 滴答
10 | - 维护全局变量jiffies --- 记录从开机到当前时间的时钟中断发生次数 kernel/sched.c
11 | - set_intr_gate(0x20,&timer_interrupt) sched_init里面时间中断处理函数
12 | - incl jiffies # 增加时钟中断发生次数的值---滴答数 kernel/system_call里 10ms产生一个滴答
13 | + 寻找状态切换点
14 | - sys_fork 实现了fork功能 kernel/system_call里
15 | - copy_process 真正意义上实现来进程的创建 kernel/fork.c里面
16 | - 在 copy_process 中输出新建+就绪 log
17 | - 记录睡眠 sleep_on() interruptible_sleep_on() kernel/sched.c
18 | - 一系列的记录Log
19 | + 编译取出Log分析
20 | + 修改时间片分析Log变化
21 |
22 |
--------------------------------------------------------------------------------
/lab3/process-20.log:
--------------------------------------------------------------------------------
1 | 1 N 48
2 | 1 J 48
3 | 0 J 48
4 | 1 R 48
5 | 2 N 49
6 | 2 J 49
7 | 1 W 49
8 | 2 R 49
9 | 3 N 63
10 | 3 J 64
11 | 2 E 68
12 | 1 J 68
13 | 3 R 68
14 | 3 W 74
15 | 1 R 74
16 | 4 N 74
17 | 4 J 74
18 | 1 W 74
19 | 4 R 74
20 | 5 N 106
21 | 5 J 107
22 | 4 W 107
23 | 5 R 107
24 | 4 J 109
25 | 5 E 110
26 | 4 R 110
27 | 4 W 115
28 | 0 R 115
29 | 4 J 931
30 | 4 R 931
31 | 4 W 931
32 | 0 R 931
33 | 4 J 993
34 | 4 R 994
35 | 4 W 994
36 | 0 R 994
37 | 4 J 1171
38 | 4 R 1172
39 | 4 W 1172
40 | 0 R 1172
41 | 4 J 1198
42 | 4 R 1198
43 | 4 W 1198
44 | 0 R 1198
45 | 4 J 1378
46 | 4 R 1378
47 | 4 W 1378
48 | 0 R 1378
49 | 4 J 1410
50 | 4 R 1410
51 | 4 W 1410
52 | 0 R 1410
53 | 4 J 1590
54 | 4 R 1590
55 | 4 W 1590
56 | 0 R 1590
57 | 4 J 1629
58 | 4 R 1629
59 | 4 W 1629
60 | 0 R 1629
61 | 4 J 1959
62 | 4 R 1959
63 | 6 N 1960
64 | 6 J 1961
65 | 4 W 1961
66 | 6 R 1961
67 |
--------------------------------------------------------------------------------
/lab3/process.log:
--------------------------------------------------------------------------------
1 | 1 N 48
2 | 1 J 48
3 | 0 J 48
4 | 1 R 48
5 | 2 N 49
6 | 2 J 49
7 | 1 W 49
8 | 2 R 49
9 | 3 N 63
10 | 3 J 64
11 | 2 J 64
12 | 3 R 64
13 | 3 W 68
14 | 2 R 68
15 | 2 E 73
16 | 1 J 73
17 | 1 R 73
18 | 4 N 74
19 | 4 J 74
20 | 1 W 74
21 | 4 R 74
22 | 5 N 106
23 | 5 J 106
24 | 4 W 107
25 | 5 R 107
26 | 4 J 109
27 | 5 E 109
28 | 4 R 109
29 | 4 W 115
30 | 0 R 115
31 | 4 J 782
32 | 4 R 782
33 | 4 W 782
34 | 0 R 782
35 | 4 J 810
36 | 4 R 810
37 | 4 W 810
38 | 0 R 810
39 | 4 J 932
40 | 4 R 932
41 | 4 W 932
42 | 0 R 932
43 | 4 J 958
44 | 4 R 958
45 | 4 W 958
46 | 0 R 958
47 | 4 J 1132
48 | 4 R 1132
49 | 4 W 1132
50 | 0 R 1133
51 | 4 J 1155
52 | 4 R 1155
53 | 4 W 1155
54 | 0 R 1155
55 | 4 J 1230
56 | 4 R 1231
57 | 4 W 1231
58 | 0 R 1231
59 | 4 J 1266
60 | 4 R 1266
61 | 4 W 1266
62 | 0 R 1266
63 | 4 J 1660
64 | 4 R 1660
65 | 6 N 1661
66 | 6 J 1662
67 | 4 W 1662
68 | 6 R 1662
69 |
--------------------------------------------------------------------------------
/lab2/testlab2.sh:
--------------------------------------------------------------------------------
1 | #/bin/sh
2 |
3 | string1="Sunner"
4 | string2="Richard Stallman"
5 | string3="This is a very very long string!"
6 |
7 | score1=10
8 | score2=10
9 | score3=10
10 |
11 | expected1="Sunner"
12 | expected2="Richard Stallman"
13 | expected3="Richard Stallman"
14 |
15 | echo Testing string:$string1
16 | ./iam "$string1"
17 | result=`./whoami`
18 | if [ "$result" = "$expected1" ]; then
19 | echo PASS.
20 | else
21 | score1=0
22 | echo FAILED.
23 | fi
24 | score=$score1
25 |
26 | echo Testing string:$string2
27 | ./iam "$string2"
28 | result=`./whoami`
29 | if [ "$result" = "$expected2" ]; then
30 | echo PASS.
31 | else
32 | score2=0
33 | echo FAILED.
34 | fi
35 | score=$score+$score2
36 |
37 | echo Testing string:$string3
38 | ./iam "$string3"
39 | result=`./whoami`
40 | if [ "$result" = "$expected3" ]; then
41 | echo PASS.
42 | else
43 | score3=0
44 | echo FAILED.
45 | fi
46 | score=$score+$score3
47 |
48 | let "totalscore=$score"
49 | echo Score: $score = $totalscore%
50 |
--------------------------------------------------------------------------------
/lab6/Makefile:
--------------------------------------------------------------------------------
1 | CC =gcc-3.4 -march=i386
2 | CFLAGS =-m32 -g -Wall -O -fstrength-reduce -fomit-frame-pointer \
3 | -finline-functions -nostdinc -I../include
4 | AS =as --32
5 | AR =ar
6 | LD =ld
7 | LDFLAGS =-m elf_i386
8 | CPP =gcc-3.4 -E -nostdinc -I../include
9 |
10 | .c.o:
11 | $(CC) $(CFLAGS) \
12 | -c -o $*.o $<
13 | .s.o:
14 | $(AS) -o $*.o $<
15 | .c.s:
16 | $(CC) $(CFLAGS) \
17 | -S -o $*.s $<
18 |
19 | OBJS = memory.o page.o shm.o
20 |
21 | all: mm.o
22 |
23 | mm.o: $(OBJS)
24 | $(LD) -m elf_i386 -r -o mm.o $(OBJS)
25 |
26 | clean:
27 | rm -f core *.o *.a tmp_make
28 | for i in *.c;do rm -f `basename $$i .c`.s;done
29 |
30 | dep:
31 | sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
32 | (for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
33 | cp tmp_make Makefile
34 |
35 | ### Dependencies:
36 | shm.s shm.o: shm.c ../include/linux/kernel.h ../include/unistd.h
37 | memory.o: memory.c ../include/signal.h ../include/sys/types.h \
38 | ../include/asm/system.h ../include/linux/sched.h \
39 | ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
40 | ../include/linux/kernel.h
41 |
--------------------------------------------------------------------------------
/lab6/shm.c:
--------------------------------------------------------------------------------
1 | // int shmget(char * name);
2 | // void * shmat(int shmid);
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define SHM_COUNT 20
10 | #define SHM_NAME_SIZE 20
11 |
12 | struct struct_shm_tables
13 | {
14 | int occupied;
15 | char name[SHM_NAME_SIZE];
16 | long addr;
17 | } shm_tables[SHM_COUNT];
18 |
19 | int find_shm_location(char *name)
20 | {
21 | int i;
22 | for(i=0; ibrk + current->start_code);
68 | return (void*)current->brk;
69 | }
70 |
--------------------------------------------------------------------------------
/lab6/producer.c:
--------------------------------------------------------------------------------
1 | #define __LIBRARY__
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | _syscall2(sem_t*,sem_open,const char *,name,unsigned int,value);
9 | _syscall1(int,sem_wait,sem_t*,sem);
10 | _syscall1(int,sem_post,sem_t*,sem);
11 | _syscall1(int,sem_unlink,const char *,name);
12 | _syscall1(void*,shmat,int,shmid);
13 | _syscall1(int,shmget,char*,name);
14 |
15 | #define NUMBER 520 /*打出数字总数*/
16 | #define BUFSIZE 10 /*缓冲区大小*/
17 |
18 | sem_t *empty, *full, *mutex;
19 |
20 | int main()
21 | {
22 | int i,shmid;
23 | int *p;
24 | int buf_in = 0; /*写入缓冲区位置*/
25 | /*打开信号量*/
26 | if((mutex = sem_open("carpelamutex",1)) == SEM_FAILED)
27 | {
28 | perror("sem_open() error!\n");
29 | return -1;
30 | }
31 | if((empty = sem_open("carpelaempty",10)) == SEM_FAILED)
32 | {
33 | perror("sem_open() error!\n");
34 | return -1;
35 | }
36 | if((full = sem_open("carpelafull",0)) == SEM_FAILED)
37 | {
38 | perror("sem_open() error!\n");
39 | return -1;
40 | }
41 | shmid = shmget("buffer");
42 | if(shmid == -1)
43 | {
44 | return -1;
45 | }
46 | p = (int*) shmat(shmid);
47 | /*生产者进程*/
48 | for( i = 0 ; i < NUMBER; i++)
49 | {
50 | sem_wait(empty);
51 | sem_wait(mutex);
52 | p[buf_in] = i;
53 | buf_in = ( buf_in + 1)% BUFSIZE;
54 | sem_post(mutex);
55 | sem_post(full);
56 | }
57 | /*释放信号量*/
58 | sem_unlink("carpelafull");
59 | sem_unlink("carpelaempty");
60 | sem_unlink("carpelamutex");
61 | return 0;
62 | }
63 |
--------------------------------------------------------------------------------
/lab6/consumer.c:
--------------------------------------------------------------------------------
1 | #define __LIBRARY__
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | _syscall2(sem_t*,sem_open,const char *,name,unsigned int,value);
9 | _syscall1(int,sem_wait,sem_t*,sem);
10 | _syscall1(int,sem_post,sem_t*,sem);
11 | _syscall1(int,sem_unlink,const char *,name);
12 | _syscall1(void*,shmat,int,shmid);
13 | _syscall1(int,shmget,char*,name);
14 |
15 | #define NUMBER 520 /*打出数字总数*/
16 | #define BUFSIZE 10 /*缓冲区大小*/
17 |
18 | sem_t *empty, *full, *mutex;
19 |
20 | int main()
21 | {
22 | int i,shmid,data;
23 | int *p;
24 | int buf_out = 0; /*从缓冲区读取位置*/
25 | /*打开信号量*/
26 | if((mutex = sem_open("carpelamutex",1)) == SEM_FAILED)
27 | {
28 | perror("sem_open() error!\n");
29 | return -1;
30 | }
31 | if((empty = sem_open("carpelaempty",10)) == SEM_FAILED)
32 | {
33 | perror("sem_open() error!\n");
34 | return -1;
35 | }
36 | if((full = sem_open("carpelafull",0)) == SEM_FAILED)
37 | {
38 | perror("sem_open() error!\n");
39 | return -1;
40 | }
41 | shmid = shmget("buffer");
42 | if(shmid == -1)
43 | {
44 | return -1;
45 | }
46 | p = (int *)shmat(shmid);
47 |
48 | for( i = 0; i < NUMBER; i++ )
49 | {
50 | sem_wait(full);
51 | sem_wait(mutex);
52 |
53 | data = p[buf_out];
54 | buf_out = (buf_out + 1) % BUFSIZE;
55 |
56 | sem_post(mutex);
57 | sem_post(empty);
58 | /*消费资源*/
59 | printf("%d: %d\n",getpid(),data);
60 | fflush(stdout);
61 | }
62 |
63 | /*释放信号量*/
64 | sem_unlink("carpelafull");
65 | sem_unlink("carpelaempty");
66 | sem_unlink("carpelamutex");
67 |
68 | return 0;
69 | }
70 |
--------------------------------------------------------------------------------
/lab3/process.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 | /*基本数据类型*/
8 |
9 | #define HZ 100
10 |
11 | void cpuio_bound(int last, int cpu_time, int io_time);
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | pid_t proc_num[10]; /*创建10个子进程*/
16 | int i;
17 | for(i = 0; i < 10 ; i++)
18 | {
19 | proc_num[i] = fork();
20 |
21 | if(proc_num[i] == 0)
22 | {
23 | cpuio_bound(10, i, 10-i);
24 | } else if (proc_num[i] < 0)
25 | {
26 | printf("Failed in process %d\n", i+1);
27 | return -1;
28 | }
29 | }
30 |
31 | for(i = 0; i < 10; i ++)
32 | {
33 | printf("child pid: %d\n", proc_num[i]);
34 | }
35 |
36 | wait(&i);/*父进程等到所有的子进程完成然后返回*/
37 | return 0;
38 | }
39 |
40 | /*
41 | * 此函数按照参数占用CPU和I/O时间
42 | * last: 函数实际占用CPU和I/O的总时间,不含在就绪队列中的时间,>=0是必须的
43 | * cpu_time: 一次连续占用CPU的时间,>=0是必须的
44 | * io_time: 一次I/O消耗的时间,>=0是必须的
45 | * 如果last > cpu_time + io_time,则往复多次占用CPU和I/O
46 | * 所有时间的单位为秒
47 | */
48 | void cpuio_bound(int last, int cpu_time, int io_time)
49 | {
50 | struct tms start_time, current_time;
51 | clock_t utime, stime;
52 | int sleep_time;
53 |
54 | while (last > 0)
55 | {
56 | /* CPU Burst */
57 | times(&start_time);
58 | /* 其实只有t.tms_utime才是真正的CPU时间。但我们是在模拟一个
59 | * 只在用户状态运行的CPU大户,就像“for(;;);”。所以把t.tms_stime
60 | * 加上很合理。*/
61 | do
62 | {
63 | times(¤t_time);
64 | utime = current_time.tms_utime - start_time.tms_utime;
65 | stime = current_time.tms_stime - start_time.tms_stime;
66 | } while ( ( (utime + stime) / HZ ) < cpu_time );
67 | last -= cpu_time;
68 |
69 | if (last <= 0 )
70 | break;
71 |
72 | /* IO Burst */
73 | /* 用sleep(1)模拟1秒钟的I/O操作 */
74 | sleep_time=0;
75 | while (sleep_time < io_time)
76 | {
77 | sleep(1);
78 | sleep_time++;
79 | }
80 | last -= sleep_time;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/lab3/printk.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/printk.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * When in kernel-mode, we cannot use printf, as fs is liable to
9 | * point to 'interesting' things. Make a printf with fs-saving, and
10 | * all is well.
11 | */
12 | #include
13 | #include
14 |
15 | #include
16 |
17 | #include
18 | #include
19 |
20 |
21 | static char buf[1024];
22 |
23 | extern int vsprintf(char * buf, const char * fmt, va_list args);
24 |
25 | int printk(const char *fmt, ...)
26 | {
27 | va_list args;
28 | int i;
29 |
30 | va_start(args, fmt);
31 | i=vsprintf(buf,fmt,args);
32 | va_end(args);
33 | __asm__("push %%fs\n\t"
34 | "push %%ds\n\t"
35 | "pop %%fs\n\t"
36 | "pushl %0\n\t"
37 | "pushl $buf\n\t"
38 | "pushl $0\n\t"
39 | "call tty_write\n\t"
40 | "addl $8,%%esp\n\t"
41 | "popl %0\n\t"
42 | "pop %%fs"
43 | ::"r" (i):"ax","cx","dx");
44 | return i;
45 | }
46 |
47 |
48 | static char logbuf[1024];
49 | /*
50 | fprintk(1, "The ID of running process is %ld", current->pid); //向stdout打印正在运行的进程的ID
51 | fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'R', jiffies); //向log文件输出
52 | */
53 | int fprintk(int fd, const char *fmt, ...)
54 | {
55 | va_list args;
56 | int count;
57 | struct file * file;
58 | struct m_inode * inode;
59 |
60 | va_start(args, fmt);
61 | count=vsprintf(logbuf, fmt, args);
62 | va_end(args);
63 |
64 | if (fd < 3) /* 如果输出到stdout或stderr,直接调用sys_write即可 */
65 | {
66 | __asm__("push %%fs\n\t"
67 | "push %%ds\n\t"
68 | "pop %%fs\n\t"
69 | "pushl %0\n\t"
70 | "pushl $logbuf\n\t" /* 注意对于Windows环境来说,是_logbuf,下同 */
71 | "pushl %1\n\t"
72 | "call sys_write\n\t" /* 注意对于Windows环境来说,是_sys_write,下同 */
73 | "addl $8,%%esp\n\t"
74 | "popl %0\n\t"
75 | "pop %%fs"
76 | ::"r" (count),"r" (fd):"ax","cx","dx");
77 | }
78 | else /* 假定>=3的描述符都与文件关联。事实上,还存在很多其它情况,这里并没有考虑。*/
79 | {
80 | if (!(file=task[0]->filp[fd])) /* 从进程0的文件描述符表中得到文件句柄 */
81 | return 0;
82 | inode=file->f_inode;
83 |
84 | __asm__("push %%fs\n\t"
85 | "push %%ds\n\t"
86 | "pop %%fs\n\t"
87 | "pushl %0\n\t"
88 | "pushl $logbuf\n\t"
89 | "pushl %1\n\t"
90 | "pushl %2\n\t"
91 | "call file_write\n\t"
92 | "addl $12,%%esp\n\t"
93 | "popl %0\n\t"
94 | "pop %%fs"
95 | ::"r" (count),"r" (file),"r" (inode):"ax","cx","dx");
96 | }
97 | return count;
98 | }
99 |
--------------------------------------------------------------------------------
/lab2/sys.h:
--------------------------------------------------------------------------------
1 | extern int sys_setup();
2 | extern int sys_exit();
3 | extern int sys_fork();
4 | extern int sys_read();
5 | extern int sys_write();
6 | extern int sys_open();
7 | extern int sys_close();
8 | extern int sys_waitpid();
9 | extern int sys_creat();
10 | extern int sys_link();
11 | extern int sys_unlink();
12 | extern int sys_execve();
13 | extern int sys_chdir();
14 | extern int sys_time();
15 | extern int sys_mknod();
16 | extern int sys_chmod();
17 | extern int sys_chown();
18 | extern int sys_break();
19 | extern int sys_stat();
20 | extern int sys_lseek();
21 | extern int sys_getpid();
22 | extern int sys_mount();
23 | extern int sys_umount();
24 | extern int sys_setuid();
25 | extern int sys_getuid();
26 | extern int sys_stime();
27 | extern int sys_ptrace();
28 | extern int sys_alarm();
29 | extern int sys_fstat();
30 | extern int sys_pause();
31 | extern int sys_utime();
32 | extern int sys_stty();
33 | extern int sys_gtty();
34 | extern int sys_access();
35 | extern int sys_nice();
36 | extern int sys_ftime();
37 | extern int sys_sync();
38 | extern int sys_kill();
39 | extern int sys_rename();
40 | extern int sys_mkdir();
41 | extern int sys_rmdir();
42 | extern int sys_dup();
43 | extern int sys_pipe();
44 | extern int sys_times();
45 | extern int sys_prof();
46 | extern int sys_brk();
47 | extern int sys_setgid();
48 | extern int sys_getgid();
49 | extern int sys_signal();
50 | extern int sys_geteuid();
51 | extern int sys_getegid();
52 | extern int sys_acct();
53 | extern int sys_phys();
54 | extern int sys_lock();
55 | extern int sys_ioctl();
56 | extern int sys_fcntl();
57 | extern int sys_mpx();
58 | extern int sys_setpgid();
59 | extern int sys_ulimit();
60 | extern int sys_uname();
61 | extern int sys_umask();
62 | extern int sys_chroot();
63 | extern int sys_ustat();
64 | extern int sys_dup2();
65 | extern int sys_getppid();
66 | extern int sys_getpgrp();
67 | extern int sys_setsid();
68 | extern int sys_sigaction();
69 | extern int sys_sgetmask();
70 | extern int sys_ssetmask();
71 | extern int sys_setreuid();
72 | extern int sys_setregid();
73 | extern int sys_iam();
74 | extern int sys_whoami();
75 |
76 | fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
77 | sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
78 | sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
79 | sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
80 | sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
81 | sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
82 | sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
83 | sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
84 | sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
85 | sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
86 | sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
87 | sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
88 | sys_setreuid,sys_setregid,sys_iam,sys_whoami };
89 |
--------------------------------------------------------------------------------
/lab5/sys.h:
--------------------------------------------------------------------------------
1 | extern int sys_setup();
2 | extern int sys_exit();
3 | extern int sys_fork();
4 | extern int sys_read();
5 | extern int sys_write();
6 | extern int sys_open();
7 | extern int sys_close();
8 | extern int sys_waitpid();
9 | extern int sys_creat();
10 | extern int sys_link();
11 | extern int sys_unlink();
12 | extern int sys_execve();
13 | extern int sys_chdir();
14 | extern int sys_time();
15 | extern int sys_mknod();
16 | extern int sys_chmod();
17 | extern int sys_chown();
18 | extern int sys_break();
19 | extern int sys_stat();
20 | extern int sys_lseek();
21 | extern int sys_getpid();
22 | extern int sys_mount();
23 | extern int sys_umount();
24 | extern int sys_setuid();
25 | extern int sys_getuid();
26 | extern int sys_stime();
27 | extern int sys_ptrace();
28 | extern int sys_alarm();
29 | extern int sys_fstat();
30 | extern int sys_pause();
31 | extern int sys_utime();
32 | extern int sys_stty();
33 | extern int sys_gtty();
34 | extern int sys_access();
35 | extern int sys_nice();
36 | extern int sys_ftime();
37 | extern int sys_sync();
38 | extern int sys_kill();
39 | extern int sys_rename();
40 | extern int sys_mkdir();
41 | extern int sys_rmdir();
42 | extern int sys_dup();
43 | extern int sys_pipe();
44 | extern int sys_times();
45 | extern int sys_prof();
46 | extern int sys_brk();
47 | extern int sys_setgid();
48 | extern int sys_getgid();
49 | extern int sys_signal();
50 | extern int sys_geteuid();
51 | extern int sys_getegid();
52 | extern int sys_acct();
53 | extern int sys_phys();
54 | extern int sys_lock();
55 | extern int sys_ioctl();
56 | extern int sys_fcntl();
57 | extern int sys_mpx();
58 | extern int sys_setpgid();
59 | extern int sys_ulimit();
60 | extern int sys_uname();
61 | extern int sys_umask();
62 | extern int sys_chroot();
63 | extern int sys_ustat();
64 | extern int sys_dup2();
65 | extern int sys_getppid();
66 | extern int sys_getpgrp();
67 | extern int sys_setsid();
68 | extern int sys_sigaction();
69 | extern int sys_sgetmask();
70 | extern int sys_ssetmask();
71 | extern int sys_setreuid();
72 | extern int sys_setregid();
73 | extern int sys_sem_open();
74 | extern int sys_sem_wait();
75 | extern int sys_sem_post();
76 | extern int sys_sem_unlink();
77 |
78 | fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
79 | sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
80 | sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
81 | sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
82 | sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
83 | sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
84 | sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
85 | sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
86 | sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
87 | sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
88 | sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
89 | sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
90 | sys_setreuid,sys_setregid, sys_sem_open, sys_sem_wait, sys_sem_post, sys_sem_unlink };
91 |
--------------------------------------------------------------------------------
/lab6/sys.h:
--------------------------------------------------------------------------------
1 | extern int sys_setup();
2 | extern int sys_exit();
3 | extern int sys_fork();
4 | extern int sys_read();
5 | extern int sys_write();
6 | extern int sys_open();
7 | extern int sys_close();
8 | extern int sys_waitpid();
9 | extern int sys_creat();
10 | extern int sys_link();
11 | extern int sys_unlink();
12 | extern int sys_execve();
13 | extern int sys_chdir();
14 | extern int sys_time();
15 | extern int sys_mknod();
16 | extern int sys_chmod();
17 | extern int sys_chown();
18 | extern int sys_break();
19 | extern int sys_stat();
20 | extern int sys_lseek();
21 | extern int sys_getpid();
22 | extern int sys_mount();
23 | extern int sys_umount();
24 | extern int sys_setuid();
25 | extern int sys_getuid();
26 | extern int sys_stime();
27 | extern int sys_ptrace();
28 | extern int sys_alarm();
29 | extern int sys_fstat();
30 | extern int sys_pause();
31 | extern int sys_utime();
32 | extern int sys_stty();
33 | extern int sys_gtty();
34 | extern int sys_access();
35 | extern int sys_nice();
36 | extern int sys_ftime();
37 | extern int sys_sync();
38 | extern int sys_kill();
39 | extern int sys_rename();
40 | extern int sys_mkdir();
41 | extern int sys_rmdir();
42 | extern int sys_dup();
43 | extern int sys_pipe();
44 | extern int sys_times();
45 | extern int sys_prof();
46 | extern int sys_brk();
47 | extern int sys_setgid();
48 | extern int sys_getgid();
49 | extern int sys_signal();
50 | extern int sys_geteuid();
51 | extern int sys_getegid();
52 | extern int sys_acct();
53 | extern int sys_phys();
54 | extern int sys_lock();
55 | extern int sys_ioctl();
56 | extern int sys_fcntl();
57 | extern int sys_mpx();
58 | extern int sys_setpgid();
59 | extern int sys_ulimit();
60 | extern int sys_uname();
61 | extern int sys_umask();
62 | extern int sys_chroot();
63 | extern int sys_ustat();
64 | extern int sys_dup2();
65 | extern int sys_getppid();
66 | extern int sys_getpgrp();
67 | extern int sys_setsid();
68 | extern int sys_sigaction();
69 | extern int sys_sgetmask();
70 | extern int sys_ssetmask();
71 | extern int sys_setreuid();
72 | extern int sys_setregid();
73 | extern int sys_sem_open();
74 | extern int sys_sem_wait();
75 | extern int sys_sem_post();
76 | extern int sys_sem_unlink();
77 | extern int sys_shmget();
78 | extern void* sys_shmat();
79 |
80 | fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
81 | sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
82 | sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
83 | sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
84 | sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
85 | sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
86 | sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
87 | sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
88 | sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
89 | sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
90 | sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
91 | sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
92 | sys_setreuid,sys_setregid, sys_sem_open, sys_sem_wait, sys_sem_post, sys_sem_unlink,
93 | sys_shmget, sys_shmat };
94 |
--------------------------------------------------------------------------------
/lab5/pc.c:
--------------------------------------------------------------------------------
1 | #define __LIBRARY__
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | _syscall2(sem_t*,sem_open,const char *,name,unsigned int,value);
9 | _syscall1(int,sem_wait,sem_t*,sem);
10 | _syscall1(int,sem_post,sem_t*,sem);
11 | _syscall1(int,sem_unlink,const char *,name);
12 |
13 | #define NUMBER 520 /*打出数字总数*/
14 | #define CHILD 5 /*消费者进程数*/
15 | #define BUFSIZE 10 /*缓冲区大小*/
16 |
17 | sem_t *empty, *full, *mutex;
18 | int fno; /*文件描述符*/
19 |
20 | int main()
21 | {
22 | int i,j,k;
23 | int data;
24 | pid_t p;
25 | int buf_out = 0; /*从缓冲区读取位置*/
26 | int buf_in = 0; /*写入缓冲区位置*/
27 | /*打开信号量*/
28 | if((mutex = sem_open("carmutex",1)) == SEM_FAILED)
29 | {
30 | perror("sem_open() error!\n");
31 | return -1;
32 | }
33 | if((empty = sem_open("carempty",10)) == SEM_FAILED)
34 | {
35 | perror("sem_open() error!\n");
36 | return -1;
37 | }
38 | if((full = sem_open("carfull",0)) == SEM_FAILED)
39 | {
40 | perror("sem_open() error!\n");
41 | return -1;
42 | }
43 | fno = open("buffer.dat",O_CREAT|O_RDWR|O_TRUNC,0666);
44 | /* 将待读取位置存入buffer后,以便 子进程 之间通信 */
45 | lseek(fno,10*sizeof(int),SEEK_SET);
46 | write(fno,(char *)&buf_out,sizeof(int));
47 | /*生产者进程*/
48 | if((p=fork())==0)
49 | {
50 | for( i = 0 ; i < NUMBER; i++)
51 | {
52 | sem_wait(empty);
53 | sem_wait(mutex);
54 | /*写入一个字符*/
55 | lseek(fno, buf_in*sizeof(int), SEEK_SET);
56 | write(fno,(char *)&i,sizeof(int));
57 | buf_in = ( buf_in + 1)% BUFSIZE;
58 |
59 | sem_post(mutex);
60 | sem_post(full);
61 | }
62 | return 0;
63 | }else if(p < 0)
64 | {
65 | perror("Fail to fork!\n");
66 | return -1;
67 | }
68 |
69 | for( j = 0; j < CHILD ; j++ )
70 | {
71 | if((p=fork())==0)
72 | {
73 | for( k = 0; k < NUMBER/CHILD; k++ )
74 | {
75 | sem_wait(full);
76 | sem_wait(mutex);
77 | /*获得读取位置*/
78 | lseek(fno,10*sizeof(int),SEEK_SET);
79 | read(fno,(char *)&buf_out,sizeof(int));
80 | /*读取数据*/
81 | lseek(fno,buf_out*sizeof(int),SEEK_SET);
82 | read(fno,(char *)&data,sizeof(int));
83 | /*写入读取位置*/
84 | buf_out = (buf_out + 1) % BUFSIZE;
85 | lseek(fno,10*sizeof(int),SEEK_SET);
86 | write(fno,(char *)&buf_out,sizeof(int));
87 |
88 | sem_post(mutex);
89 | sem_post(empty);
90 | /*消费资源*/
91 | printf("%d: %d\n",getpid(),data);
92 | fflush(stdout);
93 | }
94 | return 0;
95 | }else if(p<0)
96 | {
97 | perror("Fail to fork!\n");
98 | return -1;
99 | }
100 | }
101 | wait(NULL);
102 | /*释放信号量*/
103 | sem_unlink("carfull");
104 | sem_unlink("carempty");
105 | sem_unlink("carmutex");
106 | /*释放资源*/
107 | close(fno);
108 | return 0;
109 | }
110 |
--------------------------------------------------------------------------------
/lab7/read_write.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/fs/read_write.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos);
16 | extern int read_pipe(struct m_inode * inode, char * buf, int count);
17 | extern int write_pipe(struct m_inode * inode, char * buf, int count);
18 | extern int block_read(int dev, off_t * pos, char * buf, int count);
19 | extern int block_write(int dev, off_t * pos, char * buf, int count);
20 | extern int file_read(struct m_inode * inode, struct file * filp,
21 | char * buf, int count);
22 | extern int file_write(struct m_inode * inode, struct file * filp,
23 | char * buf, int count);
24 |
25 | int sys_lseek(unsigned int fd,off_t offset, int origin)
26 | {
27 | struct file * file;
28 | int tmp;
29 |
30 | if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
31 | || !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
32 | return -EBADF;
33 | if (file->f_inode->i_pipe)
34 | return -ESPIPE;
35 | switch (origin) {
36 | case 0:
37 | if (offset<0) return -EINVAL;
38 | file->f_pos=offset;
39 | break;
40 | case 1:
41 | if (file->f_pos+offset<0) return -EINVAL;
42 | file->f_pos += offset;
43 | break;
44 | case 2:
45 | if ((tmp=file->f_inode->i_size+offset) < 0)
46 | return -EINVAL;
47 | file->f_pos = tmp;
48 | break;
49 | default:
50 | return -EINVAL;
51 | }
52 | return file->f_pos;
53 | }
54 |
55 | int sys_read(unsigned int fd,char * buf,int count)
56 | {
57 | struct file * file;
58 | struct m_inode * inode;
59 |
60 | if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
61 | return -EINVAL;
62 | if (!count)
63 | return 0;
64 | verify_area(buf,count);
65 | inode = file->f_inode;
66 | if (inode->i_pipe)
67 | return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
68 | if (S_ISCHR(inode->i_mode))
69 | return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
70 | if (S_ISBLK(inode->i_mode))
71 | return block_read(inode->i_zone[0],&file->f_pos,buf,count);
72 | if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
73 | if (count+file->f_pos > inode->i_size)
74 | count = inode->i_size - file->f_pos;
75 | if (count<=0)
76 | return 0;
77 | return file_read(inode,file,buf,count);
78 | }
79 | printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
80 | return -EINVAL;
81 | }
82 |
83 | int sys_write(unsigned int fd,char * buf,int count)
84 | {
85 | struct file * file;
86 | struct m_inode * inode;
87 |
88 | if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
89 | return -EINVAL;
90 | if (!count)
91 | return 0;
92 | inode=file->f_inode;
93 | if (inode->i_pipe)
94 | return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
95 | if (S_ISCHR(inode->i_mode))
96 | return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
97 | if (S_ISBLK(inode->i_mode))
98 | return block_write(inode->i_zone[0],&file->f_pos,buf,count);
99 | if (S_ISREG(inode->i_mode))
100 | return file_write(inode,file,buf,count);
101 | printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
102 | return -EINVAL;
103 | }
104 |
--------------------------------------------------------------------------------
/lab2/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Makefile for the FREAX-kernel.
3 | #
4 | # Note! Dependencies are done automagically by 'make dep', which also
5 | # removes any old dependencies. DON'T put your own dependencies here
6 | # unless it's something special (ie not a .c file).
7 | #
8 |
9 | AR =ar
10 | AS =as --32
11 | LD =ld
12 | LDFLAGS =-m elf_i386 -x
13 | CC =gcc-3.4 -march=i386
14 | CFLAGS =-m32 -g -Wall -O -fstrength-reduce -fomit-frame-pointer \
15 | -finline-functions -nostdinc -I../include
16 | CPP =gcc-3.4 -E -nostdinc -I../include
17 |
18 | .c.s:
19 | $(CC) $(CFLAGS) \
20 | -S -o $*.s $<
21 | .s.o:
22 | $(AS) -o $*.o $<
23 | .c.o:
24 | $(CC) $(CFLAGS) \
25 | -c -o $*.o $<
26 |
27 | OBJS = sched.o system_call.o traps.o asm.o fork.o \
28 | panic.o printk.o vsprintf.o sys.o exit.o \
29 | signal.o mktime.o who.o
30 |
31 | kernel.o: $(OBJS)
32 | $(LD) -m elf_i386 -r -o kernel.o $(OBJS)
33 | sync
34 |
35 | clean:
36 | rm -f core *.o *.a tmp_make keyboard.s
37 | for i in *.c;do rm -f `basename $$i .c`.s;done
38 | (cd chr_drv; make clean)
39 | (cd blk_drv; make clean)
40 | (cd math; make clean)
41 |
42 | dep:
43 | sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
44 | (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
45 | $(CPP) -M $$i;done) >> tmp_make
46 | cp tmp_make Makefile
47 | (cd chr_drv; make dep)
48 | (cd blk_drv; make dep)
49 |
50 | ### Dependencies:
51 | who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
52 | exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
53 | ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
54 | ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
55 | ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
56 | ../include/asm/segment.h
57 | fork.s fork.o: fork.c ../include/errno.h ../include/linux/sched.h \
58 | ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
59 | ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
60 | ../include/asm/segment.h ../include/asm/system.h
61 | mktime.s mktime.o: mktime.c ../include/time.h
62 | panic.s panic.o: panic.c ../include/linux/kernel.h ../include/linux/sched.h \
63 | ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
64 | ../include/linux/mm.h ../include/signal.h
65 | printk.s printk.o: printk.c ../include/stdarg.h ../include/stddef.h \
66 | ../include/linux/kernel.h
67 | sched.s sched.o: sched.c ../include/linux/sched.h ../include/linux/head.h \
68 | ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
69 | ../include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \
70 | ../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \
71 | ../include/asm/segment.h
72 | signal.s signal.o: signal.c ../include/linux/sched.h ../include/linux/head.h \
73 | ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
74 | ../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h
75 | sys.s sys.o: sys.c ../include/errno.h ../include/linux/sched.h \
76 | ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
77 | ../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
78 | ../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \
79 | ../include/sys/times.h ../include/sys/utsname.h
80 | traps.s traps.o: traps.c ../include/string.h ../include/linux/head.h \
81 | ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
82 | ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
83 | ../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h
84 | vsprintf.s vsprintf.o: vsprintf.c ../include/stdarg.h ../include/string.h
85 |
--------------------------------------------------------------------------------
/lab5/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Makefile for the FREAX-kernel.
3 | #
4 | # Note! Dependencies are done automagically by 'make dep', which also
5 | # removes any old dependencies. DON'T put your own dependencies here
6 | # unless it's something special (ie not a .c file).
7 | #
8 |
9 | AR =ar
10 | AS =as --32
11 | LD =ld
12 | LDFLAGS =-m elf_i386 -x
13 | CC =gcc-3.4 -march=i386
14 | CFLAGS =-m32 -g -Wall -O -fstrength-reduce -fomit-frame-pointer \
15 | -finline-functions -nostdinc -I../include
16 | CPP =gcc-3.4 -E -nostdinc -I../include
17 |
18 | .c.s:
19 | $(CC) $(CFLAGS) \
20 | -S -o $*.s $<
21 | .s.o:
22 | $(AS) -o $*.o $<
23 | .c.o:
24 | $(CC) $(CFLAGS) \
25 | -c -o $*.o $<
26 |
27 | OBJS = sched.o system_call.o traps.o asm.o fork.o \
28 | panic.o printk.o vsprintf.o sys.o exit.o \
29 | signal.o mktime.o sem.o
30 |
31 | kernel.o: $(OBJS)
32 | $(LD) -m elf_i386 -r -o kernel.o $(OBJS)
33 | sync
34 |
35 | clean:
36 | rm -f core *.o *.a tmp_make keyboard.s
37 | for i in *.c;do rm -f `basename $$i .c`.s;done
38 | (cd chr_drv; make clean)
39 | (cd blk_drv; make clean)
40 | (cd math; make clean)
41 |
42 | dep:
43 | sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
44 | (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
45 | $(CPP) -M $$i;done) >> tmp_make
46 | cp tmp_make Makefile
47 | (cd chr_drv; make dep)
48 | (cd blk_drv; make dep)
49 |
50 | ### Dependencies:
51 | sem.s sem.o: sem.c ../include/linux/kernel.h ../include/unistd.h
52 | exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
53 | ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
54 | ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
55 | ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
56 | ../include/asm/segment.h
57 | fork.s fork.o: fork.c ../include/errno.h ../include/linux/sched.h \
58 | ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
59 | ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
60 | ../include/asm/segment.h ../include/asm/system.h
61 | mktime.s mktime.o: mktime.c ../include/time.h
62 | panic.s panic.o: panic.c ../include/linux/kernel.h ../include/linux/sched.h \
63 | ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
64 | ../include/linux/mm.h ../include/signal.h
65 | printk.s printk.o: printk.c ../include/stdarg.h ../include/stddef.h \
66 | ../include/linux/kernel.h
67 | sched.s sched.o: sched.c ../include/linux/sched.h ../include/linux/head.h \
68 | ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
69 | ../include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \
70 | ../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \
71 | ../include/asm/segment.h
72 | signal.s signal.o: signal.c ../include/linux/sched.h ../include/linux/head.h \
73 | ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
74 | ../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h
75 | sys.s sys.o: sys.c ../include/errno.h ../include/linux/sched.h \
76 | ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
77 | ../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
78 | ../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \
79 | ../include/sys/times.h ../include/sys/utsname.h
80 | traps.s traps.o: traps.c ../include/string.h ../include/linux/head.h \
81 | ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
82 | ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
83 | ../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h
84 | vsprintf.s vsprintf.o: vsprintf.c ../include/stdarg.h ../include/string.h
85 |
--------------------------------------------------------------------------------
/lab5/sem.c:
--------------------------------------------------------------------------------
1 | #define __LIBRARY__
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define SEM_COUNT 32
9 | sem_t semaphores[SEM_COUNT];
10 | /*队列相关操作,rear始终是下一个待写入的位置,front始终是队列第一个元素*/
11 | void init_queue(sem_queue* q)
12 | {
13 | q->front = q->rear = 0;
14 | }
15 |
16 | int is_empty(sem_queue* q)
17 | {
18 | return q->front == q->rear?1:0;
19 | }
20 | /*留下标QUE_LEN-1不用,判断是否慢*/
21 | int is_full(sem_queue* q)
22 | {
23 | return (q->rear+1)%QUE_LEN == q->front?1:0;
24 | }
25 | /*获得队列头第一个任务*/
26 | struct task_struct * get_task(sem_queue* q)
27 | {
28 | if(is_empty(q))
29 | {
30 | printk("Queue is empty!\n");
31 | return NULL;
32 | }
33 | struct task_struct *tmp = q->wait_tasks[q->front];
34 | q->front = (q->front+1)%QUE_LEN;
35 | return tmp;
36 | }
37 | /*任务插入队列尾*/
38 | int insert_task(struct task_struct *p,sem_queue* q)
39 | {
40 | // printk("Insert %d",p->pid);
41 | if(is_full(q))
42 | {
43 | printk("Queue is full!\n");
44 | return -1;
45 | }
46 | q->wait_tasks[q->rear] = p;
47 | q->rear = (q->rear+1)%QUE_LEN;
48 | return 1;
49 | }
50 | /*信号量是否已打开,是返回位置*/
51 | int sem_location(const char* name)
52 | {
53 | int i;
54 | for(i = 0;i < SEM_COUNT; i++)
55 | {
56 | if(strcmp(name,semaphores[i].name) == 0 && semaphores[i].occupied == 1)
57 | {
58 | return i;
59 | }
60 | }
61 | return -1;
62 | }
63 | /*打开信号量*/
64 | sem_t* sys_sem_open(const char* name,unsigned int value)
65 | {
66 | char tmp[16];
67 | char c;
68 | int i;
69 | for( i = 0; i<16; i++)
70 | {
71 | c = get_fs_byte(name+i);
72 | tmp[i] = c;
73 | if(c =='\0') break;
74 | }
75 | if(c >= 16)
76 | {
77 | printk("Semaphore name is too long!");
78 | return NULL;
79 | }
80 | if((i = sem_location(tmp)) != -1)
81 | {
82 | return &semaphores[i];
83 | }
84 | for(i = 0;i< SEM_COUNT; i++)
85 | {
86 | if(!semaphores[i].occupied)
87 | {
88 | strcpy(semaphores[i].name,tmp);
89 | semaphores[i].occupied = 1;
90 | semaphores[i].value = value;
91 | init_queue(&(semaphores[i].wait_queue));
92 | // printk("%d %d %d %s\n",semaphores[i].occupied,i,semaphores[i].value,semaphores[i].name);
93 | // printk("%p\n",&semaphores[i]);
94 | return &semaphores[i];
95 | }
96 | }
97 | printk("Numbers of semaphores are limited!\n");
98 | return NULL;
99 | }
100 | /*P原子操作*/
101 | int sys_sem_wait(sem_t* sem)
102 | {
103 | cli();
104 | sem->value--;
105 | if(sem->value < 0)
106 | {
107 | /*参见sleep_on*/
108 | current->state = TASK_UNINTERRUPTIBLE;
109 | insert_task(current,&(sem->wait_queue));
110 | schedule();
111 | }
112 | sti();
113 | return 0;
114 | }
115 | /*V原子操作*/
116 | int sys_sem_post(sem_t* sem)
117 | {
118 | cli();
119 | struct task_struct *p;
120 | sem->value++;
121 | if(sem->value <= 0)
122 | {
123 | p = get_task(&(sem->wait_queue));
124 | if(p != NULL)
125 | {
126 | (*p).state = TASK_RUNNING;
127 | }
128 | }
129 | sti();
130 | return 0;
131 | }
132 | /*释放信号量*/
133 | int sys_sem_unlink(const char *name)
134 | {
135 | char tmp[16];
136 | char c;
137 | int i;
138 | for( i = 0; i<16; i++)
139 | {
140 | c = get_fs_byte(name+i);
141 | tmp[i] = c;
142 | if(c =='\0') break;
143 | }
144 | if(c >= 16)
145 | {
146 | printk("Semphore name is too long!");
147 | return -1;
148 | }
149 | int ret = sem_location(tmp);
150 | if(ret != -1)
151 | {
152 | semaphores[ret].value = 0;
153 | strcpy(semaphores[ret].name,"\0");
154 | semaphores[ret].occupied = 0;
155 | return 0;
156 | }
157 | return -1;
158 | }
159 |
--------------------------------------------------------------------------------
/lab1/setup.s:
--------------------------------------------------------------------------------
1 | !
2 | ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
3 | ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
4 | ! versions of linux
5 | !
6 | SYSSIZE = 0x3000
7 | !
8 | ! bootsect.s (C) 1991 Linus Torvalds
9 | !
10 | ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
11 | ! iself out of the way to address 0x90000, and jumps there.
12 | !
13 | ! It then loads 'setup' directly after itself (0x90200), and the system
14 | ! at 0x10000, using BIOS interrupts.
15 | !
16 | ! NOTE! currently system is at most 8*65536 bytes long. This should be no
17 | ! problem, even in the future. I want to keep it simple. This 512 kB
18 | ! kernel size should be enough, especially as this doesn't contain the
19 | ! buffer cache as in minix
20 | !
21 | ! The loader has been made as simple as possible, and continuos
22 | ! read errors will result in a unbreakable loop. Reboot by hand. It
23 | ! loads pretty fast by getting whole sectors at a time whenever possible.
24 |
25 | .globl begtext, begdata, begbss, endtext, enddata, endbss
26 | .text
27 | begtext:
28 | .data
29 | begdata:
30 | .bss
31 | begbss:
32 | .text
33 |
34 | SETUPLEN = 4 ! nr of setup-sectors
35 | BOOTSEG = 0x07c0 ! original address of boot-sector
36 | INITSEG = 0x9000 ! we move boot here - out of the way
37 | SETUPSEG = 0x9020 ! setup starts here
38 | SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
39 | ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
40 |
41 | ! ROOT_DEV: 0x000 - same type of floppy as boot.
42 | ! 0x301 - first partition on first drive etc
43 | ROOT_DEV = 0x306
44 |
45 | entry _start
46 | _start:
47 | mov ax,cs
48 | mov ds,ax
49 |
50 | mov es,ax
51 |
52 | mov ah,#0x03 ! read cursor pos
53 | xor bh,bh
54 | int 0x10
55 |
56 | mov cx,#28
57 | mov bx,#0x0007 ! page 0, attribute 7 (normal)
58 | mov bp,#msg1
59 | mov ax,#0x1301 ! write string, move cursor
60 | int 0x10
61 |
62 | ! ok, we've written the message, now
63 |
64 | ! 光标 0x9000:0
65 |
66 | mov ax,#INITSEG
67 | mov ds,ax
68 | mov ah,#0x03
69 | xor bh,bh
70 | int 0x10
71 | mov [0],dx !将光标的位置写入0x9000:0
72 |
73 | ! memory 0x9000:2
74 |
75 | mov ah,#0x88
76 | int 0x15
77 | mov [2],ax
78 |
79 |
80 | ! 重置ds为0x9000
81 | mov ax,#INITSEG
82 | mov ds,ax
83 | mov ax,#SETUPSEG
84 | mov es,ax
85 |
86 | !显示字符串
87 | mov ah,#0x03
88 | xor bh,bh
89 | int 0x10
90 | mov cx,#11
91 | mov bx,#0x007
92 | mov bp,#cur
93 | mov ax,#0x1301
94 | int 0x10
95 |
96 | !输出
97 | mov ax,[0]
98 | call print_hex
99 | call print_nl
100 |
101 | !显示字符串--内存
102 | mov ah,#0x03
103 | xor bh,bh
104 | int 0x10
105 | mov cx,#12
106 | mov bx,#0x007
107 | mov bp,#mem
108 | mov ax,#0x1301
109 | int 0x10
110 |
111 | !显示信息
112 | mov ax,[2]
113 | call print_hex
114 | call print_nl
115 |
116 |
117 | ! 循环啊喂!!!
118 |
119 | l: jmp l
120 | print_hex:
121 | mov cx,#4 ! 4个十六进制数字
122 | mov dx,ax ! 将ax所指的值放入dx中,ax作为参数传递寄存器
123 | print_digit:
124 | rol dx,#4 ! 循环以使低4比特用上 !! 取dx的高4比特移到低4比特处。
125 | mov ax,#0xe0f ! ah = 请求的功能值,al = 半字节(4个比特)掩码。
126 | and al,dl ! 取dl的低4比特值。
127 | add al,#0x30 ! 给al数字加上十六进制0x30
128 | cmp al,#0x3a
129 | jl outp !是一个不大于十的数字
130 | add al,#0x07 !是a~f,要多加7
131 | outp:
132 | int 0x10
133 | loop print_digit
134 | ret
135 |
136 | !打印回车换行
137 | print_nl:
138 | mov ax,#0xe0d
139 | int 0x10
140 | mov al,#0xa
141 | int 0x10
142 | ret
143 |
144 | msg1:
145 | .byte 13,10
146 | .ascii "Now we are in SETUP..."
147 | .byte 13,10,13,10
148 |
149 | cur:
150 | .ascii "Cursor POS:"
151 |
152 | mem:
153 | .ascii "Memory Size:"
154 |
155 |
156 |
157 | .text
158 | endtext:
159 | .data
160 | enddata:
161 | .bss
162 | endbss:
163 |
--------------------------------------------------------------------------------
/lab5/bin.txt:
--------------------------------------------------------------------------------
1 | 24: 0
2 | 24: 1
3 | 24: 2
4 | 24: 3
5 | 24: 4
6 | 24: 5
7 | 23: 6
8 | 22: 7
9 | 21: 8
10 | 20: 9
11 | 23: 10
12 | 23: 11
13 | 23: 12
14 | 23: 13
15 | 23: 14
16 | 23: 15
17 | 21: 16
18 | 20: 17
19 | 21: 18
20 | 21: 19
21 | 21: 20
22 | 21: 21
23 | 21: 22
24 | 21: 23
25 | 20: 24
26 | 20: 25
27 | 20: 26
28 | 20: 27
29 | 20: 28
30 | 20: 29
31 | 20: 30
32 | 24: 31
33 | 24: 32
34 | 24: 33
35 | 24: 34
36 | 24: 35
37 | 24: 36
38 | 24: 37
39 | 24: 38
40 | 24: 39
41 | 24: 40
42 | 24: 41
43 | 24: 42
44 | 23: 43
45 | 22: 44
46 | 21: 45
47 | 20: 46
48 | 24: 47
49 | 24: 48
50 | 24: 49
51 | 24: 50
52 | 24: 51
53 | 24: 52
54 | 23: 53
55 | 22: 54
56 | 20: 55
57 | 24: 56
58 | 24: 57
59 | 24: 58
60 | 24: 59
61 | 24: 60
62 | 24: 61
63 | 22: 62
64 | 20: 63
65 | 22: 64
66 | 22: 65
67 | 22: 66
68 | 22: 67
69 | 22: 68
70 | 22: 69
71 | 20: 70
72 | 20: 71
73 | 20: 72
74 | 20: 73
75 | 20: 74
76 | 20: 75
77 | 20: 76
78 | 20: 77
79 | 20: 78
80 | 20: 79
81 | 20: 80
82 | 20: 81
83 | 20: 82
84 | 24: 83
85 | 23: 84
86 | 22: 85
87 | 21: 86
88 | 20: 87
89 | 20: 88
90 | 20: 89
91 | 20: 90
92 | 20: 91
93 | 20: 92
94 | 24: 93
95 | 23: 94
96 | 21: 95
97 | 20: 96
98 | 20: 97
99 | 20: 98
100 | 20: 99
101 | 20: 100
102 | 20: 101
103 | 23: 102
104 | 21: 103
105 | 23: 104
106 | 23: 105
107 | 23: 106
108 | 23: 107
109 | 23: 108
110 | 23: 109
111 | 21: 110
112 | 20: 111
113 | 21: 112
114 | 21: 113
115 | 21: 114
116 | 21: 115
117 | 21: 116
118 | 21: 117
119 | 20: 118
120 | 20: 119
121 | 20: 120
122 | 20: 121
123 | 20: 122
124 | 20: 123
125 | 20: 124
126 | 20: 125
127 | 20: 126
128 | 20: 127
129 | 20: 128
130 | 20: 129
131 | 20: 130
132 | 24: 131
133 | 23: 132
134 | 22: 133
135 | 21: 134
136 | 20: 135
137 | 20: 136
138 | 20: 137
139 | 20: 138
140 | 20: 139
141 | 20: 140
142 | 24: 141
143 | 22: 142
144 | 21: 143
145 | 24: 144
146 | 24: 145
147 | 24: 146
148 | 24: 147
149 | 24: 148
150 | 24: 149
151 | 22: 150
152 | 21: 151
153 | 20: 152
154 | 22: 153
155 | 22: 154
156 | 22: 155
157 | 22: 156
158 | 22: 157
159 | 22: 158
160 | 21: 159
161 | 20: 160
162 | 21: 161
163 | 21: 162
164 | 21: 163
165 | 21: 164
166 | 21: 165
167 | 21: 166
168 | 20: 167
169 | 20: 168
170 | 20: 169
171 | 20: 170
172 | 20: 171
173 | 20: 172
174 | 20: 173
175 | 24: 174
176 | 24: 175
177 | 24: 176
178 | 24: 177
179 | 24: 178
180 | 24: 179
181 | 24: 180
182 | 24: 181
183 | 24: 182
184 | 24: 183
185 | 24: 184
186 | 24: 185
187 | 23: 186
188 | 22: 187
189 | 21: 188
190 | 20: 189
191 | 24: 190
192 | 24: 191
193 | 24: 192
194 | 24: 193
195 | 24: 194
196 | 24: 195
197 | 23: 196
198 | 22: 197
199 | 20: 198
200 | 24: 199
201 | 24: 200
202 | 24: 201
203 | 24: 202
204 | 24: 203
205 | 24: 204
206 | 22: 205
207 | 20: 206
208 | 22: 207
209 | 22: 208
210 | 22: 209
211 | 22: 210
212 | 22: 211
213 | 22: 212
214 | 20: 213
215 | 20: 214
216 | 20: 215
217 | 20: 216
218 | 20: 217
219 | 20: 218
220 | 20: 219
221 | 20: 220
222 | 20: 221
223 | 20: 222
224 | 20: 223
225 | 20: 224
226 | 20: 225
227 | 24: 226
228 | 23: 227
229 | 22: 228
230 | 21: 229
231 | 20: 230
232 | 20: 231
233 | 20: 232
234 | 20: 233
235 | 20: 234
236 | 20: 235
237 | 24: 236
238 | 23: 237
239 | 21: 238
240 | 20: 239
241 | 20: 240
242 | 20: 241
243 | 20: 242
244 | 20: 243
245 | 20: 244
246 | 23: 245
247 | 21: 246
248 | 23: 247
249 | 23: 248
250 | 23: 249
251 | 23: 250
252 | 23: 251
253 | 23: 252
254 | 21: 253
255 | 20: 254
256 | 21: 255
257 | 21: 256
258 | 21: 257
259 | 21: 258
260 | 21: 259
261 | 21: 260
262 | 20: 261
263 | 20: 262
264 | 20: 263
265 | 20: 264
266 | 20: 265
267 | 20: 266
268 | 20: 267
269 | 24: 268
270 | 24: 269
271 | 24: 270
272 | 24: 271
273 | 24: 272
274 | 24: 273
275 | 24: 274
276 | 24: 275
277 | 24: 276
278 | 24: 277
279 | 24: 278
280 | 24: 279
281 | 23: 280
282 | 23: 281
283 | 23: 282
284 | 23: 283
285 | 23: 284
286 | 23: 285
287 | 22: 286
288 | 22: 287
289 | 22: 288
290 | 22: 289
291 | 22: 290
292 | 22: 291
293 | 21: 292
294 | 21: 293
295 | 21: 294
296 | 21: 295
297 | 21: 296
298 | 21: 297
299 | 21: 298
300 | 21: 299
301 | 21: 300
302 | 21: 301
303 | 21: 302
304 | 21: 303
305 | 20: 304
306 | 20: 305
307 |
--------------------------------------------------------------------------------
/lab6/README.md:
--------------------------------------------------------------------------------
1 | ## 跟踪地址翻译
2 |
3 | 调试进bochs,进linux0.11,编译运行test.c
4 |
5 | 查各项参数--- LDT表 | GDT表 | 线性地址 | 页表。 然后计算出 i 的物理地址,通过修改物理内存的方式让程序退出
6 |
7 | - ./dbg-asm 调试启动
8 |
9 | - c 继续执行
10 |
11 | - 编译运行test.c, 死循环....
12 |
13 | - crtl+c 暂停运行
14 |
15 | - 在内核的话按c。如果不是cmp的话按n单步运行,知道 000f cmp出现
16 |
17 | - u/7 从当前位置开始7条指令的反汇编代码
18 |
19 | - 变量i保存在ds:0x3004这个地址,并不停地和0进行比较,直到它为0,才会跳出循环
20 |
21 | - **开始寻找ds:0x3004对应的物理地址**
22 |
23 | - ds:0x3004是虚拟地址, ds表明这个虚拟地址在ds段
24 |
25 | - 首先要找到段表,然后通过ds的值在段表中找到ds段的具体信息,然后才能就行进行地址翻译
26 |
27 | - 每个在IA-32上运行的应用程序都有一个段表,叫LDT,段的信息叫段描述符
28 |
29 | - LDT存在于哪里?ldtr寄存器是线索的起点,通过他可以在GDT(全局描述符表)中找到LDT的物理地址
30 |
31 | - sreg 找到ldtr的值 —— 0x0068,转化为二进制 0000000001101000 ,这个数字表示LDT存在在GDT表的 1101号位置,即13号位置——**参见段选择子
32 |
33 |
34 |
35 | - 那GDT的位置在哪?就是上面执行sreg后gdtr的值,这里显示是0x00005cb8(实验指导书是0x00005cc8),这个地址是物理地址
36 |
37 | - xp/32w 0x00005cb8 (xp /32w 0x00005cc8)可以查看从该地址开始。32个字的内容,及其GDT表的前16项
38 |
39 | - GDT表的没项都是64位,8个字节。
40 |
41 | - 之前我们知道LDT在GDT表的第13位(见上面,具体每位数据的参考意义见后文)。所以我们要查找的项的地址为: 0x00005cb8 + 13 * 8(xp/2w 0x00005cb8+13*8)。得到的值是0x00005d20: 0x92d00068 0x000082fa (0x00005d30 : 0xc2d00068 0x000082f9)
42 |
43 | - 不知道计算出的对不对?执行sreg看ldtr那行的dl和dh有两点 dl=0x92d00068 dh=0x000082fa
44 |
45 | - 组合一下 0x**92d0**0068 0x**00**0082**fa** 得到 **0x00fa92d0**(00f9c2d0). 这个就是LDT的物理地址(原因见后面的段描述符介绍)
46 |
47 | - xp/8w 0x00fa92d0,显示LDT的前四项内容
48 |
49 | ```
50 | [bochs]:
51 | 0x00fa92d0 : 0x00000000 0x00000000 0x00000002 0x10c0fa00
52 | 0x00fa92e0 : 0x00003fff 0x10c0f300 0x00000000 0x00faa000
53 | ```
54 |
55 | - **段描述符的介绍**
56 |
57 | - 在保护模式下,段寄存器有另外的一个名字,叫做段选择子
58 |
59 | - 段选择子保存的主要内容是该段在段表里面的索引值
60 |
61 | - 利用这个索引就能够从段表里面选择出相应的段描述符
62 |
63 | - 简单例子
64 |
65 | - sreg
66 | - 看ds,之前是看了ldtr
67 | - ds = 0x0017
68 | - 段选择子是一个16位的寄存器
69 | - 15-3 段描述符索引 2 T1 1-0 RPL (最上面的ldtr中的1101就是第一段——段描述符索引)
70 | - RPL 是请求特权级,当访问一个段的时候,处理器要检查RPL和CPL(CPL 放在CS的位0 和位1中,用来表示当前代码的特权级)。即使程序由足够的特权级CPL来访问一个段,但是如果RPL(放在DS中,用来表示请求数据段)的特权级不够,仍然是不能够访问这个段。但是如果RPL的值大于CPL(值越大,权限越小),则用RPL的值覆盖CPL的值(应该可以理解为依据权最小的那个来决定能不能访问)。
71 | - TI 是表指示标记,如果TI=0,则表示段描述符在GDT中,则会去GDT中查找;如果是1,则会去LDT中去查(最上面的是0,顺理成章在GDT中查~)
72 | - 就上面ds的例子 0x0017 = 0000000000010111. RPL = 11,最低的特权级(很好理解,因为实在应用程序中执行)。 TI = 1, 表示在LDT中查找,查找谁? 10 = 2。。查找从LDT表中的第3个段描述符(在LDT中,从0开始编号)
73 | - LDT和GDT差不多,都是每项占8个字节 所以第三项
74 | - 找到了(。。。)dl=0x00003fff, dh=0x10c0f300 。这样的话段描述符就是0x10000000
75 | - 这个段描述符里面装的是什么?
76 | - 一个64位的二进制数。存放段的基址和段限长等重要的数据
77 | - 31-24 基地址 23 G 22 D/B 21 0 20 AVL 19-16段限长 15 P 14-13 DPL 12 S 11-8 TYPE 7-0 基地址
78 | - 31-16 基地址 15-0段限长
79 | - P(Present)是段是否存在的标记
80 | - S用来表示 是系统段描述符(S=0)还是 代码或者数据段描述符(S=1
81 | - TYPE 表示段的类型,比如数据段,代码段,可读,可写
82 | - DPL是段的权限,和前面提到的CPLRPL一起使用
83 | - G是粒度。G=0表示段限长以位为单位,G=1表示段限长以4KB为单位
84 |
85 | - 段基址和线性地址
86 |
87 | - 需要的其实是他,上面的例子中 0x10000000 ,这个就是ds段在线性地址空间的起始地址。基址?
88 | - 段基址+偏移地址 = 线性地址
89 | - ds:0x3004的线性地址: 0x10000000 + 0x3004 = 0x10003004
90 | - calc ds:0x3004就可以验证了
91 |
92 | - 页表
93 |
94 | - 好像已经知道线性地址了,接下来我们需要计算的是物理地址了。这个过程中需要查找页表
95 | - 线性地址: 页目录号+页表好+页内偏移。然后页目录表查也目录号,也表查页表号,和页内偏移加起来就是物理地址
96 | - 需要算出线性地址中的页目录号,页表号,页内偏移
97 | - 上面三者分别对应了32位线性地址的10位+10位+12位
98 | - 0x10003004 的页目录号是64 页号3 页内偏移4
99 | - IA-32架构下,页目录表的位置由CR3寄存器指引
100 | - creg , 显示0, 说明页目录表的基址为0
101 | - 看其他内容 xp/68w 0
102 | - 看到的东西就是页目录表和页表中的内容 1024个32位(4K)
103 | - 32位中的前20位是物理页框号,后面的是一些属性(最重要的是最后一位P)
104 | - 我们要找的是第65个页目录项 xp/w 0+64*4
105 | - 0x00000100: 0x00fa6027
106 | - 027是属性 P=1 页表所在的物理页框号 0x00fa6。 页表在物理内存的0x00fa6位置
107 | - 从0x00fa6开始查找3号页表项 xp/w 0x00fa6000+3*4 0x00fa600c : 0x00fa5067
108 |
109 | - 物理地址
110 |
111 | - 线性地址 0x10003004对应的物理页框号为0x00fa5067 , 页内偏移是0x004
112 | - 0x00fa5004
113 | - 变量i的物理地址
114 | - 验证 page 0x10003004或者xp/w 0x00fa5004
115 |
116 | - 修改内存来改变i的值
117 |
118 | - setpmem 0x00fa5004 4 0
119 | - 从 0x00fa5004地址开始的4个字节都为0,
120 |
121 | 找到啦,在我的电脑上是0x00fa5004
122 |
123 |
124 |
125 | ## 共享内存
126 |
127 | - **基于已经实现信号量的lab4**
128 |
129 | - 修改 include/linux/sys.h
130 |
131 | - include/unistd.h
132 |
133 | - kernel/system_call.s
134 |
135 | - mm/shm.c (含释放,所以不需要修改memory.c)
136 |
137 | - mm/Makefile
138 |
139 |
--------------------------------------------------------------------------------
/lab3/fork.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/fork.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * 'fork.c' contains the help-routines for the 'fork' system call
9 | * (see also system_call.s), and some misc functions ('verify_area').
10 | * Fork is rather simple, once you get the hang of it, but the memory
11 | * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
12 | */
13 | #include
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | extern void write_verify(unsigned long address);
21 |
22 | long last_pid=0;
23 |
24 | void verify_area(void * addr,int size)
25 | {
26 | unsigned long start;
27 |
28 | start = (unsigned long) addr;
29 | size += start & 0xfff;
30 | start &= 0xfffff000;
31 | start += get_base(current->ldt[2]);
32 | while (size>0) {
33 | size -= 4096;
34 | write_verify(start);
35 | start += 4096;
36 | }
37 | }
38 |
39 | int copy_mem(int nr,struct task_struct * p)
40 | {
41 | unsigned long old_data_base,new_data_base,data_limit;
42 | unsigned long old_code_base,new_code_base,code_limit;
43 |
44 | code_limit=get_limit(0x0f);
45 | data_limit=get_limit(0x17);
46 | old_code_base = get_base(current->ldt[1]);
47 | old_data_base = get_base(current->ldt[2]);
48 | if (old_data_base != old_code_base)
49 | panic("We don't support separate I&D");
50 | if (data_limit < code_limit)
51 | panic("Bad data_limit");
52 | new_data_base = new_code_base = nr * 0x4000000;
53 | p->start_code = new_code_base;
54 | set_base(p->ldt[1],new_code_base);
55 | set_base(p->ldt[2],new_data_base);
56 | if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
57 | printk("free_page_tables: from copy_mem\n");
58 | free_page_tables(new_data_base,data_limit);
59 | return -ENOMEM;
60 | }
61 | return 0;
62 | }
63 |
64 | /*
65 | * Ok, this is the main fork-routine. It copies the system process
66 | * information (task[nr]) and sets up the necessary registers. It
67 | * also copies the data segment in it's entirety.
68 | */
69 | int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
70 | long ebx,long ecx,long edx,
71 | long fs,long es,long ds,
72 | long eip,long cs,long eflags,long esp,long ss)
73 | {
74 | struct task_struct *p;
75 | int i;
76 | struct file *f;
77 |
78 | p = (struct task_struct *) get_free_page(); //获得一个task_struct结构体空间
79 | if (!p)
80 | return -EAGAIN;
81 | task[nr] = p;
82 | *p = *current; /* NOTE! this doesn't copy the supervisor stack *//*用来复制父进程的PCB数据信息,包括priority和counter*/
83 | p->state = TASK_UNINTERRUPTIBLE;
84 | p->pid = last_pid;
85 | p->father = current->pid;
86 | p->counter = p->priority; /*初始化counter*/
87 | p->signal = 0;
88 | p->alarm = 0;
89 | p->leader = 0; /* process leadership doesn't inherit */
90 | p->utime = p->stime = 0;
91 | p->cutime = p->cstime = 0;
92 | p->start_time = jiffies; /*设置start_time为jiffies*/
93 |
94 | fprintk(3,"%d\tN\t%d\n",p->pid,jiffies); /*新建进程,pid N jiffies,在3上面的打印log */
95 |
96 | p->tss.back_link = 0;
97 | p->tss.esp0 = PAGE_SIZE + (long) p;
98 | p->tss.ss0 = 0x10;
99 | p->tss.eip = eip;
100 | p->tss.eflags = eflags;
101 | p->tss.eax = 0;
102 | p->tss.ecx = ecx;
103 | p->tss.edx = edx;
104 | p->tss.ebx = ebx;
105 | p->tss.esp = esp;
106 | p->tss.ebp = ebp;
107 | p->tss.esi = esi;
108 | p->tss.edi = edi;
109 | p->tss.es = es & 0xffff;
110 | p->tss.cs = cs & 0xffff;
111 | p->tss.ss = ss & 0xffff;
112 | p->tss.ds = ds & 0xffff;
113 | p->tss.fs = fs & 0xffff;
114 | p->tss.gs = gs & 0xffff;
115 | p->tss.ldt = _LDT(nr);
116 | p->tss.trace_bitmap = 0x80000000;
117 | if (last_task_used_math == current)
118 | __asm__("clts ; fnsave %0"::"m" (p->tss.i387));
119 | if (copy_mem(nr,p)) {
120 | task[nr] = NULL;
121 | free_page((long) p);
122 | return -EAGAIN;
123 | }
124 | for (i=0; ifilp[i]))
126 | f->f_count++;
127 | if (current->pwd)
128 | current->pwd->i_count++;
129 | if (current->root)
130 | current->root->i_count++;
131 | if (current->executable)
132 | current->executable->i_count++;
133 | set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
134 | set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
135 | p->state = TASK_RUNNING; /* do this last, just in case 进行的状态为就绪态*/
136 | /*进行->就绪*/
137 | fprintk(3,"%d\tJ\t%d\n",p->pid,jiffies); /*就绪进程,pid J jiffies,在3上面的打印log */
138 |
139 | return last_pid;
140 | }
141 |
142 | int find_empty_process(void)
143 | {
144 | int i;
145 |
146 | repeat:
147 | if ((++last_pid)<0) last_pid=1;
148 | for(i=0 ; ipid == last_pid) goto repeat;
150 | for(i=1 ; i
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | int sys_pause(void);
17 | int sys_close(int fd);
18 |
19 | void release(struct task_struct * p)
20 | {
21 | int i;
22 |
23 | if (!p)
24 | return;
25 | for (i=1 ; i32)
38 | return -EINVAL;
39 | if (priv || (current->euid==p->euid) || suser())
40 | p->signal |= (1<<(sig-1));
41 | else
42 | return -EPERM;
43 | return 0;
44 | }
45 |
46 | static void kill_session(void)
47 | {
48 | struct task_struct **p = NR_TASKS + task;
49 |
50 | while (--p > &FIRST_TASK) {
51 | if (*p && (*p)->session == current->session)
52 | (*p)->signal |= 1<<(SIGHUP-1);
53 | }
54 | }
55 |
56 | /*
57 | * XXX need to check permissions needed to send signals to process
58 | * groups, etc. etc. kill() permissions semantics are tricky!
59 | */
60 | int sys_kill(int pid,int sig)
61 | {
62 | struct task_struct **p = NR_TASKS + task;
63 | int err, retval = 0;
64 |
65 | if (!pid) while (--p > &FIRST_TASK) {
66 | if (*p && (*p)->pgrp == current->pid)
67 | if ((err=send_sig(sig,*p,1)))
68 | retval = err;
69 | } else if (pid>0) while (--p > &FIRST_TASK) {
70 | if (*p && (*p)->pid == pid)
71 | if ((err=send_sig(sig,*p,0)))
72 | retval = err;
73 | } else if (pid == -1) while (--p > &FIRST_TASK) {
74 | if ((err = send_sig(sig,*p,0)))
75 | retval = err;
76 | } else while (--p > &FIRST_TASK)
77 | if (*p && (*p)->pgrp == -pid)
78 | if ((err = send_sig(sig,*p,0)))
79 | retval = err;
80 | return retval;
81 | }
82 |
83 | static void tell_father(int pid)
84 | {
85 | int i;
86 |
87 | if (pid)
88 | for (i=0;ipid != pid)
92 | continue;
93 | task[i]->signal |= (1<<(SIGCHLD-1));
94 | return;
95 | }
96 | /* if we don't find any fathers, we just release ourselves */
97 | /* This is not really OK. Must change it to make father 1 */
98 | printk("BAD BAD - no father found\n\r");
99 | release(current);
100 | }
101 |
102 | int do_exit(long code)
103 | {
104 | int i;
105 | free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
106 | free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
107 | for (i=0 ; ifather == current->pid) {
109 | task[i]->father = 1;
110 | if (task[i]->state == TASK_ZOMBIE)
111 | /* assumption task[1] is always init */
112 | (void) send_sig(SIGCHLD, task[1], 1);
113 | }
114 | for (i=0 ; ifilp[i])
116 | sys_close(i);
117 | iput(current->pwd);
118 | current->pwd=NULL;
119 | iput(current->root);
120 | current->root=NULL;
121 | iput(current->executable);
122 | current->executable=NULL;
123 | if (current->leader && current->tty >= 0)
124 | tty_table[current->tty].pgrp = 0;
125 | if (last_task_used_math == current)
126 | last_task_used_math = NULL;
127 | if (current->leader)
128 | kill_session();
129 | current->state = TASK_ZOMBIE;
130 | /*退出进程*/
131 | fprintk(3,"%d\tE\t%d\n",current->pid,jiffies);
132 | current->exit_code = code;
133 | tell_father(current->father);
134 | schedule();
135 | return (-1); /* just to suppress warnings */
136 | }
137 |
138 | int sys_exit(int error_code)
139 | {
140 | return do_exit((error_code&0xff)<<8);
141 | }
142 |
143 | int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
144 | {
145 | int flag, code;
146 | struct task_struct ** p;
147 |
148 | verify_area(stat_addr,4);
149 | repeat:
150 | flag=0;
151 | for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
152 | if (!*p || *p == current)
153 | continue;
154 | if ((*p)->father != current->pid)
155 | continue;
156 | if (pid>0) {
157 | if ((*p)->pid != pid)
158 | continue;
159 | } else if (!pid) {
160 | if ((*p)->pgrp != current->pgrp)
161 | continue;
162 | } else if (pid != -1) {
163 | if ((*p)->pgrp != -pid)
164 | continue;
165 | }
166 | switch ((*p)->state) {
167 | case TASK_STOPPED:
168 | if (!(options & WUNTRACED))
169 | continue;
170 | put_fs_long(0x7f,stat_addr);
171 | return (*p)->pid;
172 | case TASK_ZOMBIE:
173 | current->cutime += (*p)->utime;
174 | current->cstime += (*p)->stime;
175 | flag = (*p)->pid;
176 | code = (*p)->exit_code;
177 | release(*p);
178 | put_fs_long(code,stat_addr);
179 | return flag;
180 | default:
181 | flag=1;
182 | continue;
183 | }
184 | }
185 | if (flag) {
186 | if (options & WNOHANG)
187 | return 0;
188 | current->state=TASK_INTERRUPTIBLE;
189 | /*当前进程->等待状态*/
190 | fprintk(3,"%d\tW\t%d\n",current->pid,jiffies);
191 | schedule();
192 | if (!(current->signal &= ~(1<<(SIGCHLD-1))))
193 | goto repeat;
194 | else
195 | return -EINTR;
196 | }
197 | return -ECHILD;
198 | }
199 |
200 |
201 |
--------------------------------------------------------------------------------
/lab2/testlab2.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Compile: "gcc testlab2.c"
3 | * Run: "./a.out"
4 | */
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #define __LIBRARY__
12 | #include
13 |
14 | _syscall2(int, whoami,char*,name,unsigned int,size);
15 | _syscall1(int, iam, const char*, name);
16 |
17 | #define MAX_NAME_LEN 23
18 | #define NAMEBUF_SIZE (MAX_NAME_LEN + 1)
19 | /* truncate a long name to SHORT_NAME_LEN for display */
20 | #define SHORT_NAME_LEN (MAX_NAME_LEN + 2)
21 |
22 | /* name score */
23 | #define TEST_CASE { \
24 | {"x", 10, 1, NAMEBUF_SIZE, 1},\
25 | {"sunner", 10, 6, NAMEBUF_SIZE, 6},\
26 | {"Twenty-three characters", 5, 23, NAMEBUF_SIZE, 23},\
27 | {"123456789009876543211234", 5, -1, 0, -1},\
28 | {"abcdefghijklmnopqrstuvwxyz", 5, -1, 0, -1},\
29 | {"Linus Torvalds", 5, 14, NAMEBUF_SIZE, 14},\
30 | {"", 5, 0, NAMEBUF_SIZE, 0},\
31 | {"whoami(0xbalabala, 10)", 5, 22, 10, -1},\
32 | {NULL, 0, 0, 0, 0} /* End of cases */ \
33 | }
34 | /*改动一:增加size,和rval2*/
35 |
36 | int test(const char* name, int max_score, int expected_rval1, int size, int expected_rval2);
37 | void print_message(const char* msgfmt, const char* name);
38 |
39 | struct test_case
40 | {
41 | char *name;
42 | int score;
43 | int rval1; /* return value of iam() */
44 | /*改动2:增加size,和rval2定义*/
45 | int size; /*Patch for whoami,2009.11.2*/
46 | int rval2; /* return value of whoami() */
47 | };
48 |
49 | int main(void)
50 | {
51 | struct test_case cases[] = TEST_CASE;
52 |
53 | int total_score=0, i=0;
54 |
55 | while (cases[i].score != 0)
56 | {
57 | int score;
58 |
59 | printf("Test case %d:", i+1);
60 |
61 | /*改动3:增加size,和rval2的参数阿*/
62 | score = test( cases[i].name,
63 | cases[i].score,
64 | cases[i].rval1,
65 | cases[i].size,
66 | cases[i].rval2 );
67 |
68 | total_score += score;
69 | i++;
70 | }
71 |
72 | printf("Final result: %d%%\n", total_score);
73 | return 0;
74 |
75 | }
76 | /*改动4:增加size,和rval2的声明*/
77 | int test(const char* name, int max_score, int expected_rval1, int size, int expected_rval2)
78 | {
79 | int rval;
80 | int len;
81 | char * gotname;
82 | int score=-1;
83 |
84 | assert(name != NULL);
85 |
86 | print_message("name = \"%s\", length = %d...", name);
87 |
88 | /*Test iam()*/
89 | len = strlen(name);
90 | rval = iam(name);
91 | /* printf("Return value = %d\n", rval);*/
92 |
93 | /*改动5:增加的expected_rval1*/
94 | if (rval == expected_rval1)
95 | {
96 | if (rval == -1 && errno == EINVAL) /*The system call can detect bad name*/
97 | {
98 | /* print_message("Long name, %s(%d), detected.\n", name);*/
99 | printf("PASS\n");
100 | score = max_score;
101 | }
102 | else if (rval == -1 && errno != EINVAL)
103 | {
104 | printf("\nERROR iam(): Bad errno %d. It should be %d(EINVAL).\n", errno, EINVAL);
105 | score = 0;
106 | }
107 | /* iam() is good. Test whoami() next. */
108 | }
109 | else
110 | {
111 | printf("\nERROR iam(): Return value is %d. It should be %d.\n", rval, expected_rval1);
112 | score = 0;
113 | }
114 |
115 | if (score != -1)
116 | return score;
117 |
118 | /*Test whoami()*/
119 | gotname = (char*)malloc(len+1);
120 | if (gotname == NULL)
121 | exit(-1);
122 |
123 | memset(gotname, 0, len+1);
124 |
125 | /* printf("Get: buffer length = %d.\n", len+1); */
126 |
127 | rval = whoami(gotname, size);
128 | /* printf("Return value = %d\n", rval); */
129 |
130 | /*改动6:增加的expected_rval2*/
131 | /*改动++:比较多 ,但还是顺序的改改*/
132 |
133 | if(rval == expected_rval2)
134 | {
135 | if(rval == -1)
136 | {
137 | printf("PASS\n");
138 | score = max_score;
139 | }
140 | else
141 | {
142 | if (strcmp(gotname, name) == 0)
143 | {
144 | /* print_message("Great! We got %s(%d) finally!\n", gotname); */
145 | printf("PASS\n");
146 | score = max_score;
147 | }
148 | else
149 | {
150 | print_message("\nERROR whoami(): we got %s(%d). ", gotname);
151 | print_message("It should be %s(%d).\n", name);
152 | score = 0;
153 | }
154 | }
155 | }
156 | else if (rval == -1)
157 | {
158 | printf("\nERROR whoami(): Return value is -1 and errno is %d. Why?\n", errno);
159 | score = 0;
160 | }
161 | else
162 | {
163 | printf("\nERROR whoami(): Return value should be %d, not %d.\n", expected_rval2, rval);
164 | score = 0;
165 | }
166 |
167 | free(gotname);
168 | assert(score != -1);
169 |
170 | return score;
171 | }
172 |
173 | void print_message(const char* msgfmt, const char* name)
174 | {
175 | char short_name[SHORT_NAME_LEN + 4] = {0};
176 | int len;
177 |
178 | len = strlen(name);
179 |
180 | if (len == 0)
181 | {
182 | strcpy(short_name, "NULL");
183 | }
184 | else if (len <= SHORT_NAME_LEN)
185 | {
186 | strcpy(short_name, name);
187 | }
188 | else
189 | {
190 | memset(short_name, '.', SHORT_NAME_LEN+3);
191 | memcpy(short_name, name, SHORT_NAME_LEN);
192 | }
193 |
194 | printf(msgfmt, short_name, len);
195 | }
196 |
--------------------------------------------------------------------------------
/lab1/build.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/tools/build.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * This file builds a disk-image from three different files:
9 | *
10 | * - bootsect: max 510 bytes of 8086 machine code, loads the rest
11 | * - setup: max 4 sectors of 8086 machine code, sets up system parm
12 | * - system: 80386 code for actual system
13 | *
14 | * It does some checking that all files are of the correct type, and
15 | * just writes the result to stdout, removing headers and padding to
16 | * the right amount. It also writes some system data to stderr.
17 | */
18 |
19 | /*
20 | * Changes by tytso to allow root device specification
21 | */
22 |
23 | #include /* fprintf */
24 | #include
25 | #include /* contains exit */
26 | #include /* unistd.h needs this */
27 | #include
28 | #include
29 | #include /* contains read/write */
30 | #include
31 |
32 | /*
33 | * Changes by falcon to define MAJOR and MINOR for they
34 | * are not defined in current linux header file linux/fs.h,I copy it from
35 | * include/linux/fs.h directly.
36 | */
37 |
38 | #ifndef MAJOR
39 | #define MAJOR(a) (((unsigned)(a))>>8)
40 | #endif
41 | #ifndef MINOR
42 | #define MINOR(a) ((a)&0xff)
43 | #endif
44 |
45 | #define MINIX_HEADER 32
46 | #define GCC_HEADER 1024
47 |
48 | #define SYS_SIZE 0x3000
49 |
50 | /*
51 | * Changes by falcon to let this kernel Image file boot
52 | * with a root image file on the first hardware device /dev/hd1, hence, you
53 | * should prepare a root image file, and configure the bochs with
54 | * the following lines(please set the ... as suitable info):
55 | * ...
56 | * floppya: 1_44="Image", status=inserted
57 | * ata0-master: type=disk, path="/path/to/rootimage.img", mode=flat ...
58 | * ...
59 | */
60 |
61 | #define DEFAULT_MAJOR_ROOT 3
62 | #define DEFAULT_MINOR_ROOT 1
63 |
64 | /* max nr of sectors of setup: don't change unless you also change
65 | * bootsect etc */
66 | #define SETUP_SECTS 4
67 |
68 | #define STRINGIFY(x) #x
69 |
70 | void die(char * str)
71 | {
72 | fprintf(stderr,"%s\n",str);
73 | exit(1);
74 | }
75 |
76 | void usage(void)
77 | {
78 | die("Usage: build bootsect setup system [rootdev] [> image]");
79 | }
80 |
81 | int main(int argc, char ** argv)
82 | {
83 | int i,c,id;
84 | char buf[1024];
85 | char major_root, minor_root;
86 | struct stat sb;
87 |
88 | if ((argc != 4) && (argc != 5))
89 | usage();
90 | if (argc == 5) {
91 | if (strcmp(argv[4], "FLOPPY")) {
92 | if (stat(argv[4], &sb)) {
93 | perror(argv[4]);
94 | die("Couldn't stat root device.");
95 | }
96 | major_root = MAJOR(sb.st_rdev);
97 | minor_root = MINOR(sb.st_rdev);
98 | } else {
99 | major_root = 0;
100 | minor_root = 0;
101 | }
102 | } else {
103 | major_root = DEFAULT_MAJOR_ROOT;
104 | minor_root = DEFAULT_MINOR_ROOT;
105 | }
106 | fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
107 | if ((major_root != 2) && (major_root != 3) &&
108 | (major_root != 0)) {
109 | fprintf(stderr, "Illegal root device (major = %d)\n",
110 | major_root);
111 | die("Bad root device --- major #");
112 | }
113 | for (i=0;i0 ; i+=c )
160 | if (write(1,buf,c)!=c)
161 | die("Write call failed");
162 | close (id);
163 | if (i > SETUP_SECTS*512)
164 | die("Setup exceeds " STRINGIFY(SETUP_SECTS)
165 | " sectors - rewrite build/boot/setup");
166 | fprintf(stderr,"Setup is %d bytes.\n",i);
167 | for (c=0 ; c sizeof(buf))
172 | c = sizeof(buf);
173 | if (write(1,buf,c) != c)
174 | die("Write call failed");
175 | i += c;
176 | }
177 | if (strcmp(argv[3], "none") == 0) return 0;
178 | if ((id=open(argv[3],O_RDONLY,0))<0)
179 | die("Unable to open 'system'");
180 | // if (read(id,buf,GCC_HEADER) != GCC_HEADER)
181 | // die("Unable to read header of 'system'");
182 | // if (((long *) buf)[5] != 0)
183 | // die("Non-GCC header of 'system'");
184 | for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
185 | if (write(1,buf,c)!=c)
186 | die("Write call failed");
187 | close(id);
188 | fprintf(stderr,"System is %d bytes.\n",i);
189 | if (i > SYS_SIZE*16)
190 | die("System is too big");
191 | return(0);
192 | }
193 |
--------------------------------------------------------------------------------
/lab3/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/init/main.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | #define __LIBRARY__
8 | #include
9 | #include
10 |
11 | /*
12 | * we need this inline - forking from kernel space will result
13 | * in NO COPY ON WRITE (!!!), until an execve is executed. This
14 | * is no problem, but for the stack. This is handled by not letting
15 | * main() use the stack at all after fork(). Thus, no function
16 | * calls - which means inline code for fork too, as otherwise we
17 | * would use the stack upon exit from 'fork()'.
18 | *
19 | * Actually only pause and fork are needed inline, so that there
20 | * won't be any messing with the stack from main(), but we define
21 | * some others too.
22 | */
23 | static inline _syscall0(int,fork)
24 | static inline _syscall0(int,pause)
25 | static inline _syscall1(int,setup,void *,BIOS)
26 | static inline _syscall0(int,sync)
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | #include
41 |
42 | static char printbuf[1024];
43 |
44 | extern int vsprintf();
45 | extern void init(void);
46 | extern void blk_dev_init(void);
47 | extern void chr_dev_init(void);
48 | extern void hd_init(void);
49 | extern void floppy_init(void);
50 | extern void mem_init(long start, long end);
51 | extern long rd_init(long mem_start, int length);
52 | extern long kernel_mktime(struct tm * tm);
53 | extern long startup_time;
54 |
55 | /*
56 | * This is set up by the setup-routine at boot-time
57 | */
58 | #define EXT_MEM_K (*(unsigned short *)0x90002)
59 | #define DRIVE_INFO (*(struct drive_info *)0x90080)
60 | #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
61 |
62 | /*
63 | * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
64 | * and this seems to work. I anybody has more info on the real-time
65 | * clock I'd be interested. Most of this was trial and error, and some
66 | * bios-listing reading. Urghh.
67 | */
68 |
69 | #define CMOS_READ(addr) ({ \
70 | outb_p(0x80|addr,0x70); \
71 | inb_p(0x71); \
72 | })
73 |
74 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
75 |
76 | static void time_init(void)
77 | {
78 | struct tm time;
79 |
80 | do {
81 | time.tm_sec = CMOS_READ(0);
82 | time.tm_min = CMOS_READ(2);
83 | time.tm_hour = CMOS_READ(4);
84 | time.tm_mday = CMOS_READ(7);
85 | time.tm_mon = CMOS_READ(8);
86 | time.tm_year = CMOS_READ(9);
87 | } while (time.tm_sec != CMOS_READ(0));
88 | BCD_TO_BIN(time.tm_sec);
89 | BCD_TO_BIN(time.tm_min);
90 | BCD_TO_BIN(time.tm_hour);
91 | BCD_TO_BIN(time.tm_mday);
92 | BCD_TO_BIN(time.tm_mon);
93 | BCD_TO_BIN(time.tm_year);
94 | time.tm_mon--;
95 | startup_time = kernel_mktime(&time);
96 | }
97 |
98 | static long memory_end = 0;
99 | static long buffer_memory_end = 0;
100 | static long main_memory_start = 0;
101 |
102 | struct drive_info { char dummy[32]; } drive_info;
103 |
104 | void main(void) /* This really IS void, no error here. */
105 | { /* The startup routine assumes (well, ...) this */
106 | /*
107 | * Interrupts are still disabled. Do necessary setups, then
108 | * enable them
109 | */
110 | ROOT_DEV = ORIG_ROOT_DEV;
111 | drive_info = DRIVE_INFO;
112 | memory_end = (1<<20) + (EXT_MEM_K<<10);
113 | memory_end &= 0xfffff000;
114 | if (memory_end > 16*1024*1024)
115 | memory_end = 16*1024*1024;
116 | if (memory_end > 12*1024*1024)
117 | buffer_memory_end = 4*1024*1024;
118 | else if (memory_end > 6*1024*1024)
119 | buffer_memory_end = 2*1024*1024;
120 | else
121 | buffer_memory_end = 1*1024*1024;
122 | main_memory_start = buffer_memory_end;
123 | #ifdef RAMDISK
124 | main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
125 | #endif
126 | mem_init(main_memory_start,memory_end);
127 | trap_init();
128 | blk_dev_init();
129 | chr_dev_init();
130 | tty_init();
131 | time_init();
132 | sched_init();
133 | buffer_init(buffer_memory_end);
134 | hd_init();
135 | floppy_init();
136 | sti();
137 | move_to_user_mode();
138 | setup((void *) &drive_info); /*加载系统文件*/
139 | (void) open("/dev/tty0",O_RDWR,0); /*建立文件描述符0和dev/tty0相关联*/
140 | (void) dup(0);
141 | (void) dup(0);
142 | (void) open("/var/process.log",O_CREAT|O_TRUNC|O_WRONLY,06666);
143 | if (!fork()) { /* we count on this going ok */
144 | init();
145 | }
146 | /*
147 | * NOTE!! For any other task 'pause()' would mean we have to get a
148 | * signal to awaken, but task0 is the sole exception (see 'schedule()')
149 | * as task 0 gets activated at every idle moment (when no other tasks
150 | * can run). For task0 'pause()' just means we go check if some other
151 | * task can run, and if not we return here.
152 | */
153 | for(;;) pause();
154 | }
155 |
156 | static int printf(const char *fmt, ...)
157 | {
158 | va_list args;
159 | int i;
160 |
161 | va_start(args, fmt);
162 | write(1,printbuf,i=vsprintf(printbuf, fmt, args));
163 | va_end(args);
164 | return i;
165 | }
166 |
167 | static char * argv_rc[] = { "/bin/sh", NULL };
168 | static char * envp_rc[] = { "HOME=/", NULL };
169 |
170 | static char * argv[] = { "-/bin/sh",NULL };
171 | static char * envp[] = { "HOME=/usr/root", NULL };
172 |
173 | void init(void)
174 | {
175 | int pid,i;
176 |
177 |
178 | printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
179 | NR_BUFFERS*BLOCK_SIZE);
180 | printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
181 | if (!(pid=fork())) {
182 | close(0);
183 | if (open("/etc/rc",O_RDONLY,0))
184 | _exit(1);
185 | execve("/bin/sh",argv_rc,envp_rc);
186 | _exit(2);
187 | }
188 | if (pid>0)
189 | while (pid != wait(&i))
190 | /* nothing */;
191 | while (1) {
192 | if ((pid=fork())<0) {
193 | printf("Fork failed in init\r\n");
194 | continue;
195 | }
196 | if (!pid) {
197 | close(0);close(1);close(2);
198 | setsid();
199 | (void) open("/dev/tty0",O_RDWR,0);
200 | (void) dup(0);
201 | (void) dup(0);
202 | _exit(execve("/bin/sh",argv,envp));
203 | }
204 | while (1)
205 | if (pid == wait(&i))
206 | break;
207 | printf("\n\rchild %d died with code %04x\n\r",pid,i);
208 | sync();
209 | }
210 | _exit(0); /* NOTE! _exit, not exit() */
211 | }
212 |
--------------------------------------------------------------------------------
/lab1/bootsect.s:
--------------------------------------------------------------------------------
1 | !
2 | ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
3 | ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
4 | ! versions of linux
5 | !
6 | SYSSIZE = 0x3000
7 | !
8 | ! bootsect.s (C) 1991 Linus Torvalds
9 | !
10 | ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
11 | ! iself out of the way to address 0x90000, and jumps there.
12 | !
13 | ! It then loads 'setup' directly after itself (0x90200), and the system
14 | ! at 0x10000, using BIOS interrupts.
15 | !
16 | ! NOTE! currently system is at most 8*65536 bytes long. This should be no
17 | ! problem, even in the future. I want to keep it simple. This 512 kB
18 | ! kernel size should be enough, especially as this doesn't contain the
19 | ! buffer cache as in minix
20 | !
21 | ! The loader has been made as simple as possible, and continuos
22 | ! read errors will result in a unbreakable loop. Reboot by hand. It
23 | ! loads pretty fast by getting whole sectors at a time whenever possible.
24 |
25 | .globl begtext, begdata, begbss, endtext, enddata, endbss
26 | .text
27 | begtext:
28 | .data
29 | begdata:
30 | .bss
31 | begbss:
32 | .text
33 |
34 | SETUPLEN = 4 ! nr of setup-sectors
35 | BOOTSEG = 0x07c0 ! original address of boot-sector
36 | INITSEG = 0x9000 ! we move boot here - out of the way
37 | SETUPSEG = 0x9020 ! setup starts here
38 | SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
39 | ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
40 |
41 | ! ROOT_DEV: 0x000 - same type of floppy as boot.
42 | ! 0x301 - first partition on first drive etc
43 | ROOT_DEV = 0x306
44 |
45 | entry _start
46 | _start:
47 | mov ax,#BOOTSEG
48 | mov ds,ax
49 | mov ax,#INITSEG
50 | mov es,ax
51 | mov cx,#256
52 | sub si,si
53 | sub di,di
54 | rep
55 | movw
56 | jmpi go,INITSEG
57 | go: mov ax,cs
58 | mov ds,ax
59 | mov es,ax
60 | ! put stack at 0x9ff00.
61 | mov ss,ax
62 | mov sp,#0xFF00 ! arbitrary value >>512
63 |
64 | ! load the setup-sectors directly after the bootblock.
65 | ! Note that 'es' is already set up.
66 |
67 | load_setup:
68 | mov dx,#0x0000 ! drive 0, head 0
69 | mov cx,#0x0002 ! sector 2, track 0
70 | mov bx,#0x0200 ! address = 512, in INITSEG
71 | mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
72 | int 0x13 ! read it
73 | jnc ok_load_setup ! ok - continue
74 | mov dx,#0x0000
75 | mov ax,#0x0000 ! reset the diskette
76 | int 0x13
77 | j load_setup
78 |
79 | ok_load_setup:
80 |
81 | ! Get disk drive parameters, specifically nr of sectors/track
82 |
83 | mov dl,#0x00
84 | mov ax,#0x0800 ! AH=8 is get drive parameters
85 | int 0x13
86 | mov ch,#0x00
87 | seg cs
88 | mov sectors,cx
89 | mov ax,#INITSEG
90 | mov es,ax
91 |
92 | ! Print some inane message
93 |
94 | mov ah,#0x03 ! read cursor pos
95 | xor bh,bh
96 | int 0x10
97 |
98 | mov cx,#24
99 | mov bx,#0x0007 ! page 0, attribute 7 (normal)
100 | mov bp,#msg1
101 | mov ax,#0x1301 ! write string, move cursor
102 | int 0x10
103 |
104 | ! ok, we've written the message, now
105 | ! we want to load the system (at 0x10000)
106 |
107 | mov ax,#SYSSEG
108 | mov es,ax ! segment of 0x010000
109 | call read_it
110 | call kill_motor
111 |
112 | ! After that we check which root-device to use. If the device is
113 | ! defined (!= 0), nothing is done and the given device is used.
114 | ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
115 | ! on the number of sectors that the BIOS reports currently.
116 |
117 | seg cs
118 | mov ax,root_dev
119 | cmp ax,#0
120 | jne root_defined
121 | seg cs
122 | mov bx,sectors
123 | mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
124 | cmp bx,#15
125 | je root_defined
126 | mov ax,#0x021c ! /dev/PS0 - 1.44Mb
127 | cmp bx,#18
128 | je root_defined
129 | undef_root:
130 | jmp undef_root
131 | root_defined:
132 | seg cs
133 | mov root_dev,ax
134 |
135 | ! after that (everyting loaded), we jump to
136 | ! the setup-routine loaded directly after
137 | ! the bootblock:
138 |
139 | jmpi 0,SETUPSEG
140 |
141 | ! This routine loads the system at address 0x10000, making sure
142 | ! no 64kB boundaries are crossed. We try to load it as fast as
143 | ! possible, loading whole tracks whenever we can.
144 | !
145 | ! in: es - starting address segment (normally 0x1000)
146 | !
147 | sread: .word 1+SETUPLEN ! sectors read of current track
148 | head: .word 0 ! current head
149 | track: .word 0 ! current track
150 |
151 | read_it:
152 | mov ax,es
153 | test ax,#0x0fff
154 | die: jne die ! es must be at 64kB boundary
155 | xor bx,bx ! bx is starting address within segment
156 | rp_read:
157 | mov ax,es
158 | cmp ax,#ENDSEG ! have we loaded all yet?
159 | jb ok1_read
160 | ret
161 | ok1_read:
162 | seg cs
163 | mov ax,sectors
164 | sub ax,sread
165 | mov cx,ax
166 | shl cx,#9
167 | add cx,bx
168 | jnc ok2_read
169 | je ok2_read
170 | xor ax,ax
171 | sub ax,bx
172 | shr ax,#9
173 | ok2_read:
174 | call read_track
175 | mov cx,ax
176 | add ax,sread
177 | seg cs
178 | cmp ax,sectors
179 | jne ok3_read
180 | mov ax,#1
181 | sub ax,head
182 | jne ok4_read
183 | inc track
184 | ok4_read:
185 | mov head,ax
186 | xor ax,ax
187 | ok3_read:
188 | mov sread,ax
189 | shl cx,#9
190 | add bx,cx
191 | jnc rp_read
192 | mov ax,es
193 | add ax,#0x1000
194 | mov es,ax
195 | xor bx,bx
196 | jmp rp_read
197 |
198 | read_track:
199 | push ax
200 | push bx
201 | push cx
202 | push dx
203 | mov dx,track
204 | mov cx,sread
205 | inc cx
206 | mov ch,dl
207 | mov dx,head
208 | mov dh,dl
209 | mov dl,#0
210 | and dx,#0x0100
211 | mov ah,#2
212 | int 0x13
213 | jc bad_rt
214 | pop dx
215 | pop cx
216 | pop bx
217 | pop ax
218 | ret
219 | bad_rt: mov ax,#0
220 | mov dx,#0
221 | int 0x13
222 | pop dx
223 | pop cx
224 | pop bx
225 | pop ax
226 | jmp read_track
227 |
228 | !/*
229 | ! * This procedure turns off the floppy drive motor, so
230 | ! * that we enter the kernel in a known state, and
231 | ! * don't have to worry about it later.
232 | ! */
233 | kill_motor:
234 | push dx
235 | mov dx,#0x3f2
236 | mov al,#0
237 | outb
238 | pop dx
239 | ret
240 |
241 | sectors:
242 | .word 0
243 |
244 | msg1:
245 | .byte 13,10
246 | .ascii "rccoder is booting ..."
247 | .byte 13,10,13,10
248 |
249 | .org 508
250 | root_dev:
251 | .word ROOT_DEV
252 | boot_flag:
253 | .word 0xAA55
254 |
255 | .text
256 | endtext:
257 | .data
258 | enddata:
259 | .bss
260 | endbss:
261 |
--------------------------------------------------------------------------------
/lab5/system_call.s:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/system_call.s
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * system_call.s contains the system-call low-level handling routines.
9 | * This also contains the timer-interrupt handler, as some of the code is
10 | * the same. The hd- and flopppy-interrupts are also here.
11 | *
12 | * NOTE: This code handles signal-recognition, which happens every time
13 | * after a timer-interrupt and after each system call. Ordinary interrupts
14 | * don't handle signal-recognition, as that would clutter them up totally
15 | * unnecessarily.
16 | *
17 | * Stack layout in 'ret_from_system_call':
18 | *
19 | * 0(%esp) - %eax
20 | * 4(%esp) - %ebx
21 | * 8(%esp) - %ecx
22 | * C(%esp) - %edx
23 | * 10(%esp) - %fs
24 | * 14(%esp) - %es
25 | * 18(%esp) - %ds
26 | * 1C(%esp) - %eip
27 | * 20(%esp) - %cs
28 | * 24(%esp) - %eflags
29 | * 28(%esp) - %oldesp
30 | * 2C(%esp) - %oldss
31 | */
32 |
33 | SIG_CHLD = 17
34 |
35 | EAX = 0x00
36 | EBX = 0x04
37 | ECX = 0x08
38 | EDX = 0x0C
39 | FS = 0x10
40 | ES = 0x14
41 | DS = 0x18
42 | EIP = 0x1C
43 | CS = 0x20
44 | EFLAGS = 0x24
45 | OLDESP = 0x28
46 | OLDSS = 0x2C
47 |
48 | state = 0 # these are offsets into the task-struct.
49 | counter = 4
50 | priority = 8
51 | signal = 12
52 | sigaction = 16 # MUST be 16 (=len of sigaction)
53 | blocked = (33*16)
54 |
55 | # offsets within sigaction
56 | sa_handler = 0
57 | sa_mask = 4
58 | sa_flags = 8
59 | sa_restorer = 12
60 |
61 | nr_system_calls = 76
62 |
63 | /*
64 | * Ok, I get parallel printer interrupts while using the floppy for some
65 | * strange reason. Urgel. Now I just ignore them.
66 | */
67 | .globl system_call,sys_fork,timer_interrupt,sys_execve
68 | .globl hd_interrupt,floppy_interrupt,parallel_interrupt
69 | .globl device_not_available, coprocessor_error
70 |
71 | .align 2
72 | bad_sys_call:
73 | movl $-1,%eax
74 | iret
75 | .align 2
76 | reschedule:
77 | pushl $ret_from_sys_call
78 | jmp schedule
79 | .align 2
80 | system_call:
81 | cmpl $nr_system_calls-1,%eax
82 | ja bad_sys_call
83 | push %ds
84 | push %es
85 | push %fs
86 | pushl %edx
87 | pushl %ecx # push %ebx,%ecx,%edx as parameters
88 | pushl %ebx # to the system call
89 | movl $0x10,%edx # set up ds,es to kernel space
90 | mov %dx,%ds
91 | mov %dx,%es
92 | movl $0x17,%edx # fs points to local data space
93 | mov %dx,%fs
94 | call sys_call_table(,%eax,4)
95 | pushl %eax
96 | movl current,%eax
97 | cmpl $0,state(%eax) # state
98 | jne reschedule
99 | cmpl $0,counter(%eax) # counter
100 | je reschedule
101 | ret_from_sys_call:
102 | movl current,%eax # task[0] cannot have signals
103 | cmpl task,%eax
104 | je 3f
105 | cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
106 | jne 3f
107 | cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
108 | jne 3f
109 | movl signal(%eax),%ebx
110 | movl blocked(%eax),%ecx
111 | notl %ecx
112 | andl %ebx,%ecx
113 | bsfl %ecx,%ecx
114 | je 3f
115 | btrl %ecx,%ebx
116 | movl %ebx,signal(%eax)
117 | incl %ecx
118 | pushl %ecx
119 | call do_signal
120 | popl %eax
121 | 3: popl %eax
122 | popl %ebx
123 | popl %ecx
124 | popl %edx
125 | pop %fs
126 | pop %es
127 | pop %ds
128 | iret
129 |
130 | .align 2
131 | coprocessor_error:
132 | push %ds
133 | push %es
134 | push %fs
135 | pushl %edx
136 | pushl %ecx
137 | pushl %ebx
138 | pushl %eax
139 | movl $0x10,%eax
140 | mov %ax,%ds
141 | mov %ax,%es
142 | movl $0x17,%eax
143 | mov %ax,%fs
144 | pushl $ret_from_sys_call
145 | jmp math_error
146 |
147 | .align 2
148 | device_not_available:
149 | push %ds
150 | push %es
151 | push %fs
152 | pushl %edx
153 | pushl %ecx
154 | pushl %ebx
155 | pushl %eax
156 | movl $0x10,%eax
157 | mov %ax,%ds
158 | mov %ax,%es
159 | movl $0x17,%eax
160 | mov %ax,%fs
161 | pushl $ret_from_sys_call
162 | clts # clear TS so that we can use math
163 | movl %cr0,%eax
164 | testl $0x4,%eax # EM (math emulation bit)
165 | je math_state_restore
166 | pushl %ebp
167 | pushl %esi
168 | pushl %edi
169 | call math_emulate
170 | popl %edi
171 | popl %esi
172 | popl %ebp
173 | ret
174 |
175 | .align 2
176 | timer_interrupt:
177 | push %ds # save ds,es and put kernel data space
178 | push %es # into them. %fs is used by _system_call
179 | push %fs
180 | pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
181 | pushl %ecx # save those across function calls. %ebx
182 | pushl %ebx # is saved as we use that in ret_sys_call
183 | pushl %eax
184 | movl $0x10,%eax
185 | mov %ax,%ds
186 | mov %ax,%es
187 | movl $0x17,%eax
188 | mov %ax,%fs
189 | incl jiffies
190 | movb $0x20,%al # EOI to interrupt controller #1
191 | outb %al,$0x20
192 | movl CS(%esp),%eax
193 | andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
194 | pushl %eax
195 | call do_timer # 'do_timer(long CPL)' does everything from
196 | addl $4,%esp # task switching to accounting ...
197 | jmp ret_from_sys_call
198 |
199 | .align 2
200 | sys_execve:
201 | lea EIP(%esp),%eax
202 | pushl %eax
203 | call do_execve
204 | addl $4,%esp
205 | ret
206 |
207 | .align 2
208 | sys_fork:
209 | call find_empty_process
210 | testl %eax,%eax
211 | js 1f
212 | push %gs
213 | pushl %esi
214 | pushl %edi
215 | pushl %ebp
216 | pushl %eax
217 | call copy_process
218 | addl $20,%esp
219 | 1: ret
220 |
221 | hd_interrupt:
222 | pushl %eax
223 | pushl %ecx
224 | pushl %edx
225 | push %ds
226 | push %es
227 | push %fs
228 | movl $0x10,%eax
229 | mov %ax,%ds
230 | mov %ax,%es
231 | movl $0x17,%eax
232 | mov %ax,%fs
233 | movb $0x20,%al
234 | outb %al,$0xA0 # EOI to interrupt controller #1
235 | jmp 1f # give port chance to breathe
236 | 1: jmp 1f
237 | 1: xorl %edx,%edx
238 | xchgl do_hd,%edx
239 | testl %edx,%edx
240 | jne 1f
241 | movl $unexpected_hd_interrupt,%edx
242 | 1: outb %al,$0x20
243 | call *%edx # "interesting" way of handling intr.
244 | pop %fs
245 | pop %es
246 | pop %ds
247 | popl %edx
248 | popl %ecx
249 | popl %eax
250 | iret
251 |
252 | floppy_interrupt:
253 | pushl %eax
254 | pushl %ecx
255 | pushl %edx
256 | push %ds
257 | push %es
258 | push %fs
259 | movl $0x10,%eax
260 | mov %ax,%ds
261 | mov %ax,%es
262 | movl $0x17,%eax
263 | mov %ax,%fs
264 | movb $0x20,%al
265 | outb %al,$0x20 # EOI to interrupt controller #1
266 | xorl %eax,%eax
267 | xchgl do_floppy,%eax
268 | testl %eax,%eax
269 | jne 1f
270 | movl $unexpected_floppy_interrupt,%eax
271 | 1: call *%eax # "interesting" way of handling intr.
272 | pop %fs
273 | pop %es
274 | pop %ds
275 | popl %edx
276 | popl %ecx
277 | popl %eax
278 | iret
279 |
280 | parallel_interrupt:
281 | pushl %eax
282 | movb $0x20,%al
283 | outb %al,$0x20
284 | popl %eax
285 | iret
286 |
--------------------------------------------------------------------------------
/lab6/system_call.s:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/system_call.s
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * system_call.s contains the system-call low-level handling routines.
9 | * This also contains the timer-interrupt handler, as some of the code is
10 | * the same. The hd- and flopppy-interrupts are also here.
11 | *
12 | * NOTE: This code handles signal-recognition, which happens every time
13 | * after a timer-interrupt and after each system call. Ordinary interrupts
14 | * don't handle signal-recognition, as that would clutter them up totally
15 | * unnecessarily.
16 | *
17 | * Stack layout in 'ret_from_system_call':
18 | *
19 | * 0(%esp) - %eax
20 | * 4(%esp) - %ebx
21 | * 8(%esp) - %ecx
22 | * C(%esp) - %edx
23 | * 10(%esp) - %fs
24 | * 14(%esp) - %es
25 | * 18(%esp) - %ds
26 | * 1C(%esp) - %eip
27 | * 20(%esp) - %cs
28 | * 24(%esp) - %eflags
29 | * 28(%esp) - %oldesp
30 | * 2C(%esp) - %oldss
31 | */
32 |
33 | SIG_CHLD = 17
34 |
35 | EAX = 0x00
36 | EBX = 0x04
37 | ECX = 0x08
38 | EDX = 0x0C
39 | FS = 0x10
40 | ES = 0x14
41 | DS = 0x18
42 | EIP = 0x1C
43 | CS = 0x20
44 | EFLAGS = 0x24
45 | OLDESP = 0x28
46 | OLDSS = 0x2C
47 |
48 | state = 0 # these are offsets into the task-struct.
49 | counter = 4
50 | priority = 8
51 | signal = 12
52 | sigaction = 16 # MUST be 16 (=len of sigaction)
53 | blocked = (33*16)
54 |
55 | # offsets within sigaction
56 | sa_handler = 0
57 | sa_mask = 4
58 | sa_flags = 8
59 | sa_restorer = 12
60 |
61 | nr_system_calls = 78
62 |
63 | /*
64 | * Ok, I get parallel printer interrupts while using the floppy for some
65 | * strange reason. Urgel. Now I just ignore them.
66 | */
67 | .globl system_call,sys_fork,timer_interrupt,sys_execve
68 | .globl hd_interrupt,floppy_interrupt,parallel_interrupt
69 | .globl device_not_available, coprocessor_error
70 |
71 | .align 2
72 | bad_sys_call:
73 | movl $-1,%eax
74 | iret
75 | .align 2
76 | reschedule:
77 | pushl $ret_from_sys_call
78 | jmp schedule
79 | .align 2
80 | system_call:
81 | cmpl $nr_system_calls-1,%eax
82 | ja bad_sys_call
83 | push %ds
84 | push %es
85 | push %fs
86 | pushl %edx
87 | pushl %ecx # push %ebx,%ecx,%edx as parameters
88 | pushl %ebx # to the system call
89 | movl $0x10,%edx # set up ds,es to kernel space
90 | mov %dx,%ds
91 | mov %dx,%es
92 | movl $0x17,%edx # fs points to local data space
93 | mov %dx,%fs
94 | call sys_call_table(,%eax,4)
95 | pushl %eax
96 | movl current,%eax
97 | cmpl $0,state(%eax) # state
98 | jne reschedule
99 | cmpl $0,counter(%eax) # counter
100 | je reschedule
101 | ret_from_sys_call:
102 | movl current,%eax # task[0] cannot have signals
103 | cmpl task,%eax
104 | je 3f
105 | cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
106 | jne 3f
107 | cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
108 | jne 3f
109 | movl signal(%eax),%ebx
110 | movl blocked(%eax),%ecx
111 | notl %ecx
112 | andl %ebx,%ecx
113 | bsfl %ecx,%ecx
114 | je 3f
115 | btrl %ecx,%ebx
116 | movl %ebx,signal(%eax)
117 | incl %ecx
118 | pushl %ecx
119 | call do_signal
120 | popl %eax
121 | 3: popl %eax
122 | popl %ebx
123 | popl %ecx
124 | popl %edx
125 | pop %fs
126 | pop %es
127 | pop %ds
128 | iret
129 |
130 | .align 2
131 | coprocessor_error:
132 | push %ds
133 | push %es
134 | push %fs
135 | pushl %edx
136 | pushl %ecx
137 | pushl %ebx
138 | pushl %eax
139 | movl $0x10,%eax
140 | mov %ax,%ds
141 | mov %ax,%es
142 | movl $0x17,%eax
143 | mov %ax,%fs
144 | pushl $ret_from_sys_call
145 | jmp math_error
146 |
147 | .align 2
148 | device_not_available:
149 | push %ds
150 | push %es
151 | push %fs
152 | pushl %edx
153 | pushl %ecx
154 | pushl %ebx
155 | pushl %eax
156 | movl $0x10,%eax
157 | mov %ax,%ds
158 | mov %ax,%es
159 | movl $0x17,%eax
160 | mov %ax,%fs
161 | pushl $ret_from_sys_call
162 | clts # clear TS so that we can use math
163 | movl %cr0,%eax
164 | testl $0x4,%eax # EM (math emulation bit)
165 | je math_state_restore
166 | pushl %ebp
167 | pushl %esi
168 | pushl %edi
169 | call math_emulate
170 | popl %edi
171 | popl %esi
172 | popl %ebp
173 | ret
174 |
175 | .align 2
176 | timer_interrupt:
177 | push %ds # save ds,es and put kernel data space
178 | push %es # into them. %fs is used by _system_call
179 | push %fs
180 | pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
181 | pushl %ecx # save those across function calls. %ebx
182 | pushl %ebx # is saved as we use that in ret_sys_call
183 | pushl %eax
184 | movl $0x10,%eax
185 | mov %ax,%ds
186 | mov %ax,%es
187 | movl $0x17,%eax
188 | mov %ax,%fs
189 | incl jiffies
190 | movb $0x20,%al # EOI to interrupt controller #1
191 | outb %al,$0x20
192 | movl CS(%esp),%eax
193 | andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
194 | pushl %eax
195 | call do_timer # 'do_timer(long CPL)' does everything from
196 | addl $4,%esp # task switching to accounting ...
197 | jmp ret_from_sys_call
198 |
199 | .align 2
200 | sys_execve:
201 | lea EIP(%esp),%eax
202 | pushl %eax
203 | call do_execve
204 | addl $4,%esp
205 | ret
206 |
207 | .align 2
208 | sys_fork:
209 | call find_empty_process
210 | testl %eax,%eax
211 | js 1f
212 | push %gs
213 | pushl %esi
214 | pushl %edi
215 | pushl %ebp
216 | pushl %eax
217 | call copy_process
218 | addl $20,%esp
219 | 1: ret
220 |
221 | hd_interrupt:
222 | pushl %eax
223 | pushl %ecx
224 | pushl %edx
225 | push %ds
226 | push %es
227 | push %fs
228 | movl $0x10,%eax
229 | mov %ax,%ds
230 | mov %ax,%es
231 | movl $0x17,%eax
232 | mov %ax,%fs
233 | movb $0x20,%al
234 | outb %al,$0xA0 # EOI to interrupt controller #1
235 | jmp 1f # give port chance to breathe
236 | 1: jmp 1f
237 | 1: xorl %edx,%edx
238 | xchgl do_hd,%edx
239 | testl %edx,%edx
240 | jne 1f
241 | movl $unexpected_hd_interrupt,%edx
242 | 1: outb %al,$0x20
243 | call *%edx # "interesting" way of handling intr.
244 | pop %fs
245 | pop %es
246 | pop %ds
247 | popl %edx
248 | popl %ecx
249 | popl %eax
250 | iret
251 |
252 | floppy_interrupt:
253 | pushl %eax
254 | pushl %ecx
255 | pushl %edx
256 | push %ds
257 | push %es
258 | push %fs
259 | movl $0x10,%eax
260 | mov %ax,%ds
261 | mov %ax,%es
262 | movl $0x17,%eax
263 | mov %ax,%fs
264 | movb $0x20,%al
265 | outb %al,$0x20 # EOI to interrupt controller #1
266 | xorl %eax,%eax
267 | xchgl do_floppy,%eax
268 | testl %eax,%eax
269 | jne 1f
270 | movl $unexpected_floppy_interrupt,%eax
271 | 1: call *%eax # "interesting" way of handling intr.
272 | pop %fs
273 | pop %es
274 | pop %ds
275 | popl %edx
276 | popl %ecx
277 | popl %eax
278 | iret
279 |
280 | parallel_interrupt:
281 | pushl %eax
282 | movb $0x20,%al
283 | outb %al,$0x20
284 | popl %eax
285 | iret
286 |
--------------------------------------------------------------------------------
/lab2/system_call.s:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/system_call.s
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * system_call.s contains the system-call low-level handling routines.
9 | * This also contains the timer-interrupt handler, as some of the code is
10 | * the same. The hd- and flopppy-interrupts are also here.
11 | *
12 | * NOTE: This code handles signal-recognition, which happens every time
13 | * after a timer-interrupt and after each system call. Ordinary interrupts
14 | * don't handle signal-recognition, as that would clutter them up totally
15 | * unnecessarily.
16 | *
17 | * Stack layout in 'ret_from_system_call':
18 | *
19 | * 0(%esp) - %eax
20 | * 4(%esp) - %ebx
21 | * 8(%esp) - %ecx
22 | * C(%esp) - %edx
23 | * 10(%esp) - %fs
24 | * 14(%esp) - %es
25 | * 18(%esp) - %ds
26 | * 1C(%esp) - %eip
27 | * 20(%esp) - %cs
28 | * 24(%esp) - %eflags
29 | * 28(%esp) - %oldesp
30 | * 2C(%esp) - %oldss
31 | */
32 |
33 | SIG_CHLD = 17
34 |
35 | EAX = 0x00
36 | EBX = 0x04
37 | ECX = 0x08
38 | EDX = 0x0C
39 | FS = 0x10
40 | ES = 0x14
41 | DS = 0x18
42 | EIP = 0x1C
43 | CS = 0x20
44 | EFLAGS = 0x24
45 | OLDESP = 0x28
46 | OLDSS = 0x2C
47 |
48 | state = 0 # these are offsets into the task-struct.
49 | counter = 4
50 | priority = 8
51 | signal = 12
52 | sigaction = 16 # MUST be 16 (=len of sigaction)
53 | blocked = (33*16)
54 |
55 | # offsets within sigaction
56 | sa_handler = 0
57 | sa_mask = 4
58 | sa_flags = 8
59 | sa_restorer = 12
60 |
61 | /*
62 | * xi tong diao yong zong shu
63 | */
64 | nr_system_calls = 74
65 |
66 | /*
67 | * Ok, I get parallel printer interrupts while using the floppy for some
68 | * strange reason. Urgel. Now I just ignore them.
69 | */
70 | .globl system_call,sys_fork,timer_interrupt,sys_execve
71 | .globl hd_interrupt,floppy_interrupt,parallel_interrupt
72 | .globl device_not_available, coprocessor_error
73 |
74 | .align 2
75 | bad_sys_call:
76 | movl $-1,%eax
77 | iret
78 | .align 2
79 | reschedule:
80 | pushl $ret_from_sys_call
81 | jmp schedule
82 | .align 2
83 | system_call:
84 | cmpl $nr_system_calls-1,%eax
85 | ja bad_sys_call
86 | push %ds
87 | push %es
88 | push %fs
89 | pushl %edx
90 | pushl %ecx # push %ebx,%ecx,%edx as parameters
91 | pushl %ebx # to the system call
92 | movl $0x10,%edx # set up ds,es to kernel space
93 | mov %dx,%ds
94 | mov %dx,%es
95 | movl $0x17,%edx # fs points to local data space
96 | mov %dx,%fs
97 | call sys_call_table(,%eax,4)
98 | pushl %eax
99 | movl current,%eax
100 | cmpl $0,state(%eax) # state
101 | jne reschedule
102 | cmpl $0,counter(%eax) # counter
103 | je reschedule
104 | ret_from_sys_call:
105 | movl current,%eax # task[0] cannot have signals
106 | cmpl task,%eax
107 | je 3f
108 | cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
109 | jne 3f
110 | cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
111 | jne 3f
112 | movl signal(%eax),%ebx
113 | movl blocked(%eax),%ecx
114 | notl %ecx
115 | andl %ebx,%ecx
116 | bsfl %ecx,%ecx
117 | je 3f
118 | btrl %ecx,%ebx
119 | movl %ebx,signal(%eax)
120 | incl %ecx
121 | pushl %ecx
122 | call do_signal
123 | popl %eax
124 | 3: popl %eax
125 | popl %ebx
126 | popl %ecx
127 | popl %edx
128 | pop %fs
129 | pop %es
130 | pop %ds
131 | iret
132 |
133 | .align 2
134 | coprocessor_error:
135 | push %ds
136 | push %es
137 | push %fs
138 | pushl %edx
139 | pushl %ecx
140 | pushl %ebx
141 | pushl %eax
142 | movl $0x10,%eax
143 | mov %ax,%ds
144 | mov %ax,%es
145 | movl $0x17,%eax
146 | mov %ax,%fs
147 | pushl $ret_from_sys_call
148 | jmp math_error
149 |
150 | .align 2
151 | device_not_available:
152 | push %ds
153 | push %es
154 | push %fs
155 | pushl %edx
156 | pushl %ecx
157 | pushl %ebx
158 | pushl %eax
159 | movl $0x10,%eax
160 | mov %ax,%ds
161 | mov %ax,%es
162 | movl $0x17,%eax
163 | mov %ax,%fs
164 | pushl $ret_from_sys_call
165 | clts # clear TS so that we can use math
166 | movl %cr0,%eax
167 | testl $0x4,%eax # EM (math emulation bit)
168 | je math_state_restore
169 | pushl %ebp
170 | pushl %esi
171 | pushl %edi
172 | call math_emulate
173 | popl %edi
174 | popl %esi
175 | popl %ebp
176 | ret
177 |
178 | .align 2
179 | timer_interrupt:
180 | push %ds # save ds,es and put kernel data space
181 | push %es # into them. %fs is used by _system_call
182 | push %fs
183 | pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
184 | pushl %ecx # save those across function calls. %ebx
185 | pushl %ebx # is saved as we use that in ret_sys_call
186 | pushl %eax
187 | movl $0x10,%eax
188 | mov %ax,%ds
189 | mov %ax,%es
190 | movl $0x17,%eax
191 | mov %ax,%fs
192 | incl jiffies
193 | movb $0x20,%al # EOI to interrupt controller #1
194 | outb %al,$0x20
195 | movl CS(%esp),%eax
196 | andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
197 | pushl %eax
198 | call do_timer # 'do_timer(long CPL)' does everything from
199 | addl $4,%esp # task switching to accounting ...
200 | jmp ret_from_sys_call
201 |
202 | .align 2
203 | sys_execve:
204 | lea EIP(%esp),%eax
205 | pushl %eax
206 | call do_execve
207 | addl $4,%esp
208 | ret
209 |
210 | .align 2
211 | sys_fork:
212 | call find_empty_process
213 | testl %eax,%eax
214 | js 1f
215 | push %gs
216 | pushl %esi
217 | pushl %edi
218 | pushl %ebp
219 | pushl %eax
220 | call copy_process
221 | addl $20,%esp
222 | 1: ret
223 |
224 | hd_interrupt:
225 | pushl %eax
226 | pushl %ecx
227 | pushl %edx
228 | push %ds
229 | push %es
230 | push %fs
231 | movl $0x10,%eax
232 | mov %ax,%ds
233 | mov %ax,%es
234 | movl $0x17,%eax
235 | mov %ax,%fs
236 | movb $0x20,%al
237 | outb %al,$0xA0 # EOI to interrupt controller #1
238 | jmp 1f # give port chance to breathe
239 | 1: jmp 1f
240 | 1: xorl %edx,%edx
241 | xchgl do_hd,%edx
242 | testl %edx,%edx
243 | jne 1f
244 | movl $unexpected_hd_interrupt,%edx
245 | 1: outb %al,$0x20
246 | call *%edx # "interesting" way of handling intr.
247 | pop %fs
248 | pop %es
249 | pop %ds
250 | popl %edx
251 | popl %ecx
252 | popl %eax
253 | iret
254 |
255 | floppy_interrupt:
256 | pushl %eax
257 | pushl %ecx
258 | pushl %edx
259 | push %ds
260 | push %es
261 | push %fs
262 | movl $0x10,%eax
263 | mov %ax,%ds
264 | mov %ax,%es
265 | movl $0x17,%eax
266 | mov %ax,%fs
267 | movb $0x20,%al
268 | outb %al,$0x20 # EOI to interrupt controller #1
269 | xorl %eax,%eax
270 | xchgl do_floppy,%eax
271 | testl %eax,%eax
272 | jne 1f
273 | movl $unexpected_floppy_interrupt,%eax
274 | 1: call *%eax # "interesting" way of handling intr.
275 | pop %fs
276 | pop %es
277 | pop %ds
278 | popl %edx
279 | popl %ecx
280 | popl %eax
281 | iret
282 |
283 | parallel_interrupt:
284 | pushl %eax
285 | movb $0x20,%al
286 | outb %al,$0x20
287 | popl %eax
288 | iret
289 |
--------------------------------------------------------------------------------
/lab3/system_call.s:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/system_call.s
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * system_call.s contains the system-call low-level handling routines.
9 | * This also contains the timer-interrupt handler, as some of the code is
10 | * the same. The hd- and flopppy-interrupts are also here.
11 | *
12 | * NOTE: This code handles signal-recognition, which happens every time
13 | * after a timer-interrupt and after each system call. Ordinary interrupts
14 | * don't handle signal-recognition, as that would clutter them up totally
15 | * unnecessarily.
16 | *
17 | * Stack layout in 'ret_from_system_call':
18 | *
19 | * 0(%esp) - %eax
20 | * 4(%esp) - %ebx
21 | * 8(%esp) - %ecx
22 | * C(%esp) - %edx
23 | * 10(%esp) - %fs
24 | * 14(%esp) - %es
25 | * 18(%esp) - %ds
26 | * 1C(%esp) - %eip
27 | * 20(%esp) - %cs
28 | * 24(%esp) - %eflags
29 | * 28(%esp) - %oldesp
30 | * 2C(%esp) - %oldss
31 | */
32 |
33 | SIG_CHLD = 17
34 |
35 | EAX = 0x00
36 | EBX = 0x04
37 | ECX = 0x08
38 | EDX = 0x0C
39 | FS = 0x10
40 | ES = 0x14
41 | DS = 0x18
42 | EIP = 0x1C
43 | CS = 0x20
44 | EFLAGS = 0x24
45 | OLDESP = 0x28
46 | OLDSS = 0x2C
47 |
48 | state = 0 # these are offsets into the task-struct.
49 | counter = 4
50 | priority = 8
51 | signal = 12
52 | sigaction = 16 # MUST be 16 (=len of sigaction)
53 | blocked = (33*16)
54 |
55 | # offsets within sigaction
56 | sa_handler = 0
57 | sa_mask = 4
58 | sa_flags = 8
59 | sa_restorer = 12
60 |
61 | nr_system_calls = 72
62 |
63 | /*
64 | * Ok, I get parallel printer interrupts while using the floppy for some
65 | * strange reason. Urgel. Now I just ignore them.
66 | */
67 | .globl system_call,sys_fork,timer_interrupt,sys_execve
68 | .globl hd_interrupt,floppy_interrupt,parallel_interrupt
69 | .globl device_not_available, coprocessor_error
70 |
71 | .align 2
72 | bad_sys_call:
73 | movl $-1,%eax
74 | iret
75 | .align 2
76 | reschedule:
77 | pushl $ret_from_sys_call
78 | jmp schedule
79 | .align 2
80 | system_call:
81 | cmpl $nr_system_calls-1,%eax
82 | ja bad_sys_call
83 | push %ds
84 | push %es
85 | push %fs
86 | pushl %edx
87 | pushl %ecx # push %ebx,%ecx,%edx as parameters
88 | pushl %ebx # to the system call
89 | movl $0x10,%edx # set up ds,es to kernel space
90 | mov %dx,%ds
91 | mov %dx,%es
92 | movl $0x17,%edx # fs points to local data space
93 | mov %dx,%fs
94 | call sys_call_table(,%eax,4)
95 | pushl %eax
96 | movl current,%eax
97 | cmpl $0,state(%eax) # state
98 | jne reschedule
99 | cmpl $0,counter(%eax) # counter
100 | je reschedule
101 | ret_from_sys_call:
102 | movl current,%eax # task[0] cannot have signals
103 | cmpl task,%eax
104 | je 3f
105 | cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
106 | jne 3f
107 | cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
108 | jne 3f
109 | movl signal(%eax),%ebx
110 | movl blocked(%eax),%ecx
111 | notl %ecx
112 | andl %ebx,%ecx
113 | bsfl %ecx,%ecx
114 | je 3f
115 | btrl %ecx,%ebx
116 | movl %ebx,signal(%eax)
117 | incl %ecx
118 | pushl %ecx
119 | call do_signal
120 | popl %eax
121 | 3: popl %eax
122 | popl %ebx
123 | popl %ecx
124 | popl %edx
125 | pop %fs
126 | pop %es
127 | pop %ds
128 | iret
129 |
130 | .align 2
131 | coprocessor_error:
132 | push %ds
133 | push %es
134 | push %fs
135 | pushl %edx
136 | pushl %ecx
137 | pushl %ebx
138 | pushl %eax
139 | movl $0x10,%eax
140 | mov %ax,%ds
141 | mov %ax,%es
142 | movl $0x17,%eax
143 | mov %ax,%fs
144 | pushl $ret_from_sys_call
145 | jmp math_error
146 |
147 | .align 2
148 | device_not_available:
149 | push %ds
150 | push %es
151 | push %fs
152 | pushl %edx
153 | pushl %ecx
154 | pushl %ebx
155 | pushl %eax
156 | movl $0x10,%eax
157 | mov %ax,%ds
158 | mov %ax,%es
159 | movl $0x17,%eax
160 | mov %ax,%fs
161 | pushl $ret_from_sys_call
162 | clts # clear TS so that we can use math
163 | movl %cr0,%eax
164 | testl $0x4,%eax # EM (math emulation bit)
165 | je math_state_restore
166 | pushl %ebp
167 | pushl %esi
168 | pushl %edi
169 | call math_emulate
170 | popl %edi
171 | popl %esi
172 | popl %ebp
173 | ret
174 |
175 | .align 2
176 | timer_interrupt:
177 | push %ds # save ds,es and put kernel data space
178 | push %es # into them. %fs is used by _system_call
179 | push %fs
180 | pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
181 | pushl %ecx # save those across function calls. %ebx
182 | pushl %ebx # is saved as we use that in ret_sys_call
183 | pushl %eax
184 | movl $0x10,%eax
185 | mov %ax,%ds
186 | mov %ax,%es
187 | movl $0x17,%eax
188 | mov %ax,%fs
189 | incl jiffies # 增加时钟中断发生次数的值---滴答数
190 | movb $0x20,%al # EOI to interrupt controller #1
191 | outb %al,$0x20
192 | movl CS(%esp),%eax
193 | andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
194 | pushl %eax
195 | call do_timer # 'do_timer(long CPL)' does everything from
196 | addl $4,%esp # task switching to accounting ...
197 | jmp ret_from_sys_call
198 |
199 | .align 2
200 | sys_execve:
201 | lea EIP(%esp),%eax
202 | pushl %eax
203 | call do_execve
204 | addl $4,%esp
205 | ret
206 |
207 | .align 2
208 | sys_fork:
209 | call find_empty_process
210 | testl %eax,%eax
211 | js 1f
212 | push %gs # 传递参数
213 | pushl %esi
214 | pushl %edi
215 | pushl %ebp
216 | pushl %eax
217 | call copy_process # 实现进程的创建
218 | addl $20,%esp
219 | 1: ret
220 |
221 | hd_interrupt:
222 | pushl %eax
223 | pushl %ecx
224 | pushl %edx
225 | push %ds
226 | push %es
227 | push %fs
228 | movl $0x10,%eax
229 | mov %ax,%ds
230 | mov %ax,%es
231 | movl $0x17,%eax
232 | mov %ax,%fs
233 | movb $0x20,%al
234 | outb %al,$0xA0 # EOI to interrupt controller #1
235 | jmp 1f # give port chance to breathe
236 | 1: jmp 1f
237 | 1: xorl %edx,%edx
238 | xchgl do_hd,%edx
239 | testl %edx,%edx
240 | jne 1f
241 | movl $unexpected_hd_interrupt,%edx
242 | 1: outb %al,$0x20
243 | call *%edx # "interesting" way of handling intr.
244 | pop %fs
245 | pop %es
246 | pop %ds
247 | popl %edx
248 | popl %ecx
249 | popl %eax
250 | iret
251 |
252 | floppy_interrupt:
253 | pushl %eax
254 | pushl %ecx
255 | pushl %edx
256 | push %ds
257 | push %es
258 | push %fs
259 | movl $0x10,%eax
260 | mov %ax,%ds
261 | mov %ax,%es
262 | movl $0x17,%eax
263 | mov %ax,%fs
264 | movb $0x20,%al
265 | outb %al,$0x20 # EOI to interrupt controller #1
266 | xorl %eax,%eax
267 | xchgl do_floppy,%eax
268 | testl %eax,%eax
269 | jne 1f
270 | movl $unexpected_floppy_interrupt,%eax
271 | 1: call *%eax # "interesting" way of handling intr.
272 | pop %fs
273 | pop %es
274 | pop %ds
275 | popl %edx
276 | popl %ecx
277 | popl %eax
278 | iret
279 |
280 | parallel_interrupt:
281 | pushl %eax
282 | movb $0x20,%al
283 | outb %al,$0x20
284 | popl %eax
285 | iret
286 |
--------------------------------------------------------------------------------
/lab6/111:
--------------------------------------------------------------------------------
1 | 8: 0
2 | 8: 1
3 | 8: 2
4 | 8: 3
5 | 8: 4
6 | 8: 5
7 | 8: 6
8 | 8: 7
9 | 8: 8
10 | 8: 9
11 | 8: 10
12 | 8: 11
13 | 8: 12
14 | 8: 13
15 | 8: 14
16 | 8: 15
17 | 8: 16
18 | 8: 17
19 | 8: 18
20 | 8: 19
21 | 8: 20
22 | 8: 21
23 | 8: 22
24 | 8: 23
25 | 8: 24
26 | 8: 25
27 | 8: 26
28 | 8: 27
29 | 8: 28
30 | 8: 29
31 | 8: 30
32 | 8: 31
33 | 8: 32
34 | 8: 33
35 | 8: 34
36 | 8: 35
37 | 8: 36
38 | 8: 37
39 | 8: 38
40 | 8: 39
41 | 8: 40
42 | 8: 41
43 | 8: 42
44 | 8: 43
45 | 8: 44
46 | 8: 45
47 | 8: 46
48 | 8: 47
49 | 8: 48
50 | 8: 49
51 | 8: 50
52 | 8: 51
53 | 8: 52
54 | 8: 53
55 | 8: 54
56 | 8: 55
57 | 8: 56
58 | 8: 57
59 | 8: 58
60 | 8: 59
61 | 8: 60
62 | 8: 61
63 | 8: 62
64 | 8: 63
65 | 8: 64
66 | 8: 65
67 | 8: 66
68 | 8: 67
69 | 8: 68
70 | 8: 69
71 | 8: 70
72 | 8: 71
73 | 8: 72
74 | 8: 73
75 | 8: 74
76 | 8: 75
77 | 8: 76
78 | 8: 77
79 | 8: 78
80 | 8: 79
81 | 8: 80
82 | 8: 81
83 | 8: 82
84 | 8: 83
85 | 8: 84
86 | 8: 85
87 | 8: 86
88 | 8: 87
89 | 8: 88
90 | 8: 89
91 | 8: 90
92 | 8: 91
93 | 8: 92
94 | 8: 93
95 | 8: 94
96 | 8: 95
97 | 8: 96
98 | 8: 97
99 | 8: 98
100 | 8: 99
101 | 8: 100
102 | 8: 101
103 | 8: 102
104 | 8: 103
105 | 8: 104
106 | 8: 105
107 | 8: 106
108 | 8: 107
109 | 8: 108
110 | 8: 109
111 | 8: 110
112 | 8: 111
113 | 8: 112
114 | 8: 113
115 | 8: 114
116 | 8: 115
117 | 8: 116
118 | 8: 117
119 | 8: 118
120 | 8: 119
121 | 8: 120
122 | 8: 121
123 | 8: 122
124 | 8: 123
125 | 8: 124
126 | 8: 125
127 | 8: 126
128 | 8: 127
129 | 8: 128
130 | 8: 129
131 | 8: 130
132 | 8: 131
133 | 8: 132
134 | 8: 133
135 | 8: 134
136 | 8: 135
137 | 8: 136
138 | 8: 137
139 | 8: 138
140 | 8: 139
141 | 8: 140
142 | 8: 141
143 | 8: 142
144 | 8: 143
145 | 8: 144
146 | 8: 145
147 | 8: 146
148 | 8: 147
149 | 8: 148
150 | 8: 149
151 | 8: 150
152 | 8: 151
153 | 8: 152
154 | 8: 153
155 | 8: 154
156 | 8: 155
157 | 8: 156
158 | 8: 157
159 | 8: 158
160 | 8: 159
161 | 8: 160
162 | 8: 161
163 | 8: 162
164 | 8: 163
165 | 8: 164
166 | 8: 165
167 | 8: 166
168 | 8: 167
169 | 8: 168
170 | 8: 169
171 | 8: 170
172 | 8: 171
173 | 8: 172
174 | 8: 173
175 | 8: 174
176 | 8: 175
177 | 8: 176
178 | 8: 177
179 | 8: 178
180 | 8: 179
181 | 8: 180
182 | 8: 181
183 | 8: 182
184 | 8: 183
185 | 8: 184
186 | 8: 185
187 | 8: 186
188 | 8: 187
189 | 8: 188
190 | 8: 189
191 | 8: 190
192 | 8: 191
193 | 8: 192
194 | 8: 193
195 | 8: 194
196 | 8: 195
197 | 8: 196
198 | 8: 197
199 | 8: 198
200 | 8: 199
201 | 8: 200
202 | 8: 201
203 | 8: 202
204 | 8: 203
205 | 8: 204
206 | 8: 205
207 | 8: 206
208 | 8: 207
209 | 8: 208
210 | 8: 209
211 | 8: 210
212 | 8: 211
213 | 8: 212
214 | 8: 213
215 | 8: 214
216 | 8: 215
217 | 8: 216
218 | 8: 217
219 | 8: 218
220 | 8: 219
221 | 8: 220
222 | 8: 221
223 | 8: 222
224 | 8: 223
225 | 8: 224
226 | 8: 225
227 | 8: 226
228 | 8: 227
229 | 8: 228
230 | 8: 229
231 | 8: 230
232 | 8: 231
233 | 8: 232
234 | 8: 233
235 | 8: 234
236 | 8: 235
237 | 8: 236
238 | 8: 237
239 | 8: 238
240 | 8: 239
241 | 8: 240
242 | 8: 241
243 | 8: 242
244 | 8: 243
245 | 8: 244
246 | 8: 245
247 | 8: 246
248 | 8: 247
249 | 8: 248
250 | 8: 249
251 | 8: 250
252 | 8: 251
253 | 8: 252
254 | 8: 253
255 | 8: 254
256 | 8: 255
257 | 8: 256
258 | 8: 257
259 | 8: 258
260 | 8: 259
261 | 8: 260
262 | 8: 261
263 | 8: 262
264 | 8: 263
265 | 8: 264
266 | 8: 265
267 | 8: 266
268 | 8: 267
269 | 8: 268
270 | 8: 269
271 | 8: 270
272 | 8: 271
273 | 8: 272
274 | 8: 273
275 | 8: 274
276 | 8: 275
277 | 8: 276
278 | 8: 277
279 | 8: 278
280 | 8: 279
281 | 8: 280
282 | 8: 281
283 | 8: 282
284 | 8: 283
285 | 8: 284
286 | 8: 285
287 | 8: 286
288 | 8: 287
289 | 8: 288
290 | 8: 289
291 | 8: 290
292 | 8: 291
293 | 8: 292
294 | 8: 293
295 | 8: 294
296 | 8: 295
297 | 8: 296
298 | 8: 297
299 | 8: 298
300 | 8: 299
301 | 8: 300
302 | 8: 301
303 | 8: 302
304 | 8: 303
305 | 8: 304
306 | 8: 305
307 | 8: 306
308 | 8: 307
309 | 8: 308
310 | 8: 309
311 | 8: 310
312 | 8: 311
313 | 8: 312
314 | 8: 313
315 | 8: 314
316 | 8: 315
317 | 8: 316
318 | 8: 317
319 | 8: 318
320 | 8: 319
321 | 8: 320
322 | 8: 321
323 | 8: 322
324 | 8: 323
325 | 8: 324
326 | 8: 325
327 | 8: 326
328 | 8: 327
329 | 8: 328
330 | 8: 329
331 | 8: 330
332 | 8: 331
333 | 8: 332
334 | 8: 333
335 | 8: 334
336 | 8: 335
337 | 8: 336
338 | 8: 337
339 | 8: 338
340 | 8: 339
341 | 8: 340
342 | 8: 341
343 | 8: 342
344 | 8: 343
345 | 8: 344
346 | 8: 345
347 | 8: 346
348 | 8: 347
349 | 8: 348
350 | 8: 349
351 | 8: 350
352 | 8: 351
353 | 8: 352
354 | 8: 353
355 | 8: 354
356 | 8: 355
357 | 8: 356
358 | 8: 357
359 | 8: 358
360 | 8: 359
361 | 8: 360
362 | 8: 361
363 | 8: 362
364 | 8: 363
365 | 8: 364
366 | 8: 365
367 | 8: 366
368 | 8: 367
369 | 8: 368
370 | 8: 369
371 | 8: 370
372 | 8: 371
373 | 8: 372
374 | 8: 373
375 | 8: 374
376 | 8: 375
377 | 8: 376
378 | 8: 377
379 | 8: 378
380 | 8: 379
381 | 8: 380
382 | 8: 381
383 | 8: 382
384 | 8: 383
385 | 8: 384
386 | 8: 385
387 | 8: 386
388 | 8: 387
389 | 8: 388
390 | 8: 389
391 | 8: 390
392 | 8: 391
393 | 8: 392
394 | 8: 393
395 | 8: 394
396 | 8: 395
397 | 8: 396
398 | 8: 397
399 | 8: 398
400 | 8: 399
401 | 8: 400
402 | 8: 401
403 | 8: 402
404 | 8: 403
405 | 8: 404
406 | 8: 405
407 | 8: 406
408 | 8: 407
409 | 8: 408
410 | 8: 409
411 | 8: 410
412 | 8: 411
413 | 8: 412
414 | 8: 413
415 | 8: 414
416 | 8: 415
417 | 8: 416
418 | 8: 417
419 | 8: 418
420 | 8: 419
421 | 8: 420
422 | 8: 421
423 | 8: 422
424 | 8: 423
425 | 8: 424
426 | 8: 425
427 | 8: 426
428 | 8: 427
429 | 8: 428
430 | 8: 429
431 | 8: 430
432 | 8: 431
433 | 8: 432
434 | 8: 433
435 | 8: 434
436 | 8: 435
437 | 8: 436
438 | 8: 437
439 | 8: 438
440 | 8: 439
441 | 8: 440
442 | 8: 441
443 | 8: 442
444 | 8: 443
445 | 8: 444
446 | 8: 445
447 | 8: 446
448 | 8: 447
449 | 8: 448
450 | 8: 449
451 | 8: 450
452 | 8: 451
453 | 8: 452
454 | 8: 453
455 | 8: 454
456 | 8: 455
457 | 8: 456
458 | 8: 457
459 | 8: 458
460 | 8: 459
461 | 8: 460
462 | 8: 461
463 | 8: 462
464 | 8: 463
465 | 8: 464
466 | 8: 465
467 | 8: 466
468 | 8: 467
469 | 8: 468
470 | 8: 469
471 | 8: 470
472 | 8: 471
473 | 8: 472
474 | 8: 473
475 | 8: 474
476 | 8: 475
477 | 8: 476
478 | 8: 477
479 | 8: 478
480 | 8: 479
481 | 8: 480
482 | 8: 481
483 | 8: 482
484 | 8: 483
485 | 8: 484
486 | 8: 485
487 | 8: 486
488 | 8: 487
489 | 8: 488
490 | 8: 489
491 | 8: 490
492 | 8: 491
493 | 8: 492
494 | 8: 493
495 | 8: 494
496 | 8: 495
497 | 8: 496
498 | 8: 497
499 | 8: 498
500 | 8: 499
501 | 8: 500
502 | 8: 501
503 | 8: 502
504 | 8: 503
505 | 8: 504
506 | 8: 505
507 | 8: 506
508 | 8: 507
509 | 8: 508
510 | 8: 509
511 | 8: 510
512 | 8: 511
513 | 8: 512
514 | 8: 513
515 |
--------------------------------------------------------------------------------
/lab3/sched.h:
--------------------------------------------------------------------------------
1 | #ifndef _SCHED_H
2 | #define _SCHED_H
3 |
4 | #define NR_TASKS 64
5 | #define HZ 100
6 |
7 | #define FIRST_TASK task[0]
8 | #define LAST_TASK task[NR_TASKS-1]
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #if (NR_OPEN > 32)
16 | #error "Currently the close-on-exec-flags are in one word, max 32 files/proc"
17 | #endif
18 |
19 | #define TASK_RUNNING 0
20 | #define TASK_INTERRUPTIBLE 1
21 | #define TASK_UNINTERRUPTIBLE 2
22 | #define TASK_ZOMBIE 3
23 | #define TASK_STOPPED 4
24 |
25 | #ifndef NULL
26 | #define NULL ((void *) 0)
27 | #endif
28 |
29 | extern int copy_page_tables(unsigned long from, unsigned long to, long size);
30 | extern int free_page_tables(unsigned long from, unsigned long size);
31 |
32 | extern void sched_init(void);
33 | extern void schedule(void);
34 | extern void trap_init(void);
35 | #ifndef PANIC
36 | volatile void panic(const char * str);
37 | #endif
38 | extern int tty_write(unsigned minor,char * buf,int count);
39 |
40 | typedef int (*fn_ptr)();
41 |
42 | struct i387_struct {
43 | long cwd;
44 | long swd;
45 | long twd;
46 | long fip;
47 | long fcs;
48 | long foo;
49 | long fos;
50 | long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
51 | };
52 |
53 | struct tss_struct {
54 | long back_link; /* 16 high bits zero */
55 | long esp0;
56 | long ss0; /* 16 high bits zero */
57 | long esp1;
58 | long ss1; /* 16 high bits zero */
59 | long esp2;
60 | long ss2; /* 16 high bits zero */
61 | long cr3;
62 | long eip;
63 | long eflags;
64 | long eax,ecx,edx,ebx;
65 | long esp;
66 | long ebp;
67 | long esi;
68 | long edi;
69 | long es; /* 16 high bits zero */
70 | long cs; /* 16 high bits zero */
71 | long ss; /* 16 high bits zero */
72 | long ds; /* 16 high bits zero */
73 | long fs; /* 16 high bits zero */
74 | long gs; /* 16 high bits zero */
75 | long ldt; /* 16 high bits zero */
76 | long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
77 | struct i387_struct i387;
78 | };
79 |
80 | struct task_struct {
81 | /* these are hardcoded - don't touch */
82 | long state; /* -1 unrunnable, 0 runnable, >0 stopped */
83 | long counter;
84 | long priority;
85 | long signal;
86 | struct sigaction sigaction[32];
87 | long blocked; /* bitmap of masked signals */
88 | /* various fields */
89 | int exit_code;
90 | unsigned long start_code,end_code,end_data,brk,start_stack;
91 | long pid,father,pgrp,session,leader;
92 | unsigned short uid,euid,suid;
93 | unsigned short gid,egid,sgid;
94 | long alarm;
95 | long utime,stime,cutime,cstime,start_time;
96 | unsigned short used_math;
97 | /* file system info */
98 | int tty; /* -1 if no tty, so it must be signed */
99 | unsigned short umask;
100 | struct m_inode * pwd;
101 | struct m_inode * root;
102 | struct m_inode * executable;
103 | unsigned long close_on_exec;
104 | struct file * filp[NR_OPEN];
105 | /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
106 | struct desc_struct ldt[3];
107 | /* tss for this task */
108 | struct tss_struct tss;
109 | };
110 |
111 | /*
112 | * INIT_TASK is used to set up the first task table, touch at
113 | * your own risk!. Base=0, limit=0x9ffff (=640kB)
114 | */
115 | #define INIT_TASK \
116 | /* state etc */ { 0,20,20, \
117 | /* signals */ 0,{{},},0, \
118 | /* ec,brk... */ 0,0,0,0,0,0, \
119 | /* pid etc.. */ 0,-1,0,0,0, \
120 | /* uid etc */ 0,0,0,0,0,0, \
121 | /* alarm */ 0,0,0,0,0,0, \
122 | /* math */ 0, \
123 | /* fs info */ -1,0022,NULL,NULL,NULL,0, \
124 | /* filp */ {NULL,}, \
125 | { \
126 | {0,0}, \
127 | /* ldt */ {0x9f,0xc0fa00}, \
128 | {0x9f,0xc0f200}, \
129 | }, \
130 | /*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
131 | 0,0,0,0,0,0,0,0, \
132 | 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
133 | _LDT(0),0x80000000, \
134 | {} \
135 | }, \
136 | }
137 |
138 | extern struct task_struct *task[NR_TASKS];
139 | extern struct task_struct *last_task_used_math;
140 | extern struct task_struct *current;
141 | extern long volatile jiffies;
142 | extern long startup_time;
143 |
144 | #define CURRENT_TIME (startup_time+jiffies/HZ)
145 |
146 | extern void add_timer(long jiffies, void (*fn)(void));
147 | extern void sleep_on(struct task_struct ** p);
148 | extern void interruptible_sleep_on(struct task_struct ** p);
149 | extern void wake_up(struct task_struct ** p);
150 |
151 | /*
152 | * Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
153 | * 4-TSS0, 5-LDT0, 6-TSS1 etc ...
154 | */
155 | #define FIRST_TSS_ENTRY 4
156 | #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
157 | #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
158 | #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
159 | #define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
160 | #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))
161 | #define str(n) \
162 | __asm__("str %%ax\n\t" \
163 | "subl %2,%%eax\n\t" \
164 | "shrl $4,%%eax" \
165 | :"=a" (n) \
166 | :"a" (0),"i" (FIRST_TSS_ENTRY<<3))
167 | /*
168 | * switch_to(n) should switch tasks to task nr n, first
169 | * checking that n isn't the current task, in which case it does nothing.
170 | * This also clears the TS-flag if the task we switched to has used
171 | * tha math co-processor latest.
172 | */
173 | #define switch_to(n) {\
174 | struct {long a,b;} __tmp; \
175 | __asm__("cmpl %%ecx,current\n\t" \
176 | "je 1f\n\t" \
177 | "movw %%dx,%1\n\t" \
178 | "xchgl %%ecx,current\n\t" \
179 | "ljmp *%0\n\t" \
180 | "cmpl %%ecx,last_task_used_math\n\t" \
181 | "jne 1f\n\t" \
182 | "clts\n" \
183 | "1:" \
184 | ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
185 | "d" (_TSS(n)),"c" ((long) task[n])); \
186 | }
187 |
188 | #define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
189 |
190 | #define _set_base(addr,base) \
191 | __asm__ ("push %%edx\n\t" \
192 | "movw %%dx,%0\n\t" \
193 | "rorl $16,%%edx\n\t" \
194 | "movb %%dl,%1\n\t" \
195 | "movb %%dh,%2\n\t" \
196 | "pop %%edx" \
197 | ::"m" (*((addr)+2)), \
198 | "m" (*((addr)+4)), \
199 | "m" (*((addr)+7)), \
200 | "d" (base) \
201 | )
202 |
203 | #define _set_limit(addr,limit) \
204 | __asm__ ("push %%edx\n\t" \
205 | "movw %%dx,%0\n\t" \
206 | "rorl $16,%%edx\n\t" \
207 | "movb %1,%%dh\n\t" \
208 | "andb $0xf0,%%dh\n\t" \
209 | "orb %%dh,%%dl\n\t" \
210 | "movb %%dl,%1\n\t" \
211 | "pop %%edx" \
212 | ::"m" (*(addr)), \
213 | "m" (*((addr)+6)), \
214 | "d" (limit) \
215 | )
216 |
217 | #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
218 | #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
219 |
220 | /**
221 | #define _get_base(addr) ({\
222 | unsigned long __base; \
223 | __asm__("movb %3,%%dh\n\t" \
224 | "movb %2,%%dl\n\t" \
225 | "shll $16,%%edx\n\t" \
226 | "movw %1,%%dx" \
227 | :"=d" (__base) \
228 | :"m" (*((addr)+2)), \
229 | "m" (*((addr)+4)), \
230 | "m" (*((addr)+7)) \
231 | :"memory"); \
232 | __base;})
233 | **/
234 |
235 | static inline unsigned long _get_base(char * addr)
236 | {
237 | unsigned long __base;
238 | __asm__("movb %3,%%dh\n\t"
239 | "movb %2,%%dl\n\t"
240 | "shll $16,%%edx\n\t"
241 | "movw %1,%%dx"
242 | :"=&d" (__base)
243 | :"m" (*((addr)+2)),
244 | "m" (*((addr)+4)),
245 | "m" (*((addr)+7)));
246 | return __base;
247 | }
248 |
249 | #define get_base(ldt) _get_base( ((char *)&(ldt)) )
250 |
251 | #define get_limit(segment) ({ \
252 | unsigned long __limit; \
253 | __asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
254 | __limit;})
255 |
256 | #endif
257 |
--------------------------------------------------------------------------------
/lab2/unistd.h:
--------------------------------------------------------------------------------
1 | #ifndef _UNISTD_H
2 | #define _UNISTD_H
3 |
4 | /* ok, this may be a joke, but I'm working on it */
5 | #define _POSIX_VERSION 198808L
6 |
7 | #define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
8 | #define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */
9 | #define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
10 | /*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
11 | /*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
12 |
13 | #define STDIN_FILENO 0
14 | #define STDOUT_FILENO 1
15 | #define STDERR_FILENO 2
16 |
17 | #ifndef NULL
18 | #define NULL ((void *)0)
19 | #endif
20 |
21 | /* access */
22 | #define F_OK 0
23 | #define X_OK 1
24 | #define W_OK 2
25 | #define R_OK 4
26 |
27 | /* lseek */
28 | #define SEEK_SET 0
29 | #define SEEK_CUR 1
30 | #define SEEK_END 2
31 |
32 | /* _SC stands for System Configuration. We don't use them much */
33 | #define _SC_ARG_MAX 1
34 | #define _SC_CHILD_MAX 2
35 | #define _SC_CLOCKS_PER_SEC 3
36 | #define _SC_NGROUPS_MAX 4
37 | #define _SC_OPEN_MAX 5
38 | #define _SC_JOB_CONTROL 6
39 | #define _SC_SAVED_IDS 7
40 | #define _SC_VERSION 8
41 |
42 | /* more (possibly) configurable things - now pathnames */
43 | #define _PC_LINK_MAX 1
44 | #define _PC_MAX_CANON 2
45 | #define _PC_MAX_INPUT 3
46 | #define _PC_NAME_MAX 4
47 | #define _PC_PATH_MAX 5
48 | #define _PC_PIPE_BUF 6
49 | #define _PC_NO_TRUNC 7
50 | #define _PC_VDISABLE 8
51 | #define _PC_CHOWN_RESTRICTED 9
52 |
53 | #include
54 | #include
55 | #include
56 | #include
57 |
58 | #ifdef __LIBRARY__
59 |
60 | #define __NR_setup 0 /* used only by init, to get system going */
61 | #define __NR_exit 1
62 | #define __NR_fork 2
63 | #define __NR_read 3
64 | #define __NR_write 4
65 | #define __NR_open 5
66 | #define __NR_close 6
67 | #define __NR_waitpid 7
68 | #define __NR_creat 8
69 | #define __NR_link 9
70 | #define __NR_unlink 10
71 | #define __NR_execve 11
72 | #define __NR_chdir 12
73 | #define __NR_time 13
74 | #define __NR_mknod 14
75 | #define __NR_chmod 15
76 | #define __NR_chown 16
77 | #define __NR_break 17
78 | #define __NR_stat 18
79 | #define __NR_lseek 19
80 | #define __NR_getpid 20
81 | #define __NR_mount 21
82 | #define __NR_umount 22
83 | #define __NR_setuid 23
84 | #define __NR_getuid 24
85 | #define __NR_stime 25
86 | #define __NR_ptrace 26
87 | #define __NR_alarm 27
88 | #define __NR_fstat 28
89 | #define __NR_pause 29
90 | #define __NR_utime 30
91 | #define __NR_stty 31
92 | #define __NR_gtty 32
93 | #define __NR_access 33
94 | #define __NR_nice 34
95 | #define __NR_ftime 35
96 | #define __NR_sync 36
97 | #define __NR_kill 37
98 | #define __NR_rename 38
99 | #define __NR_mkdir 39
100 | #define __NR_rmdir 40
101 | #define __NR_dup 41
102 | #define __NR_pipe 42
103 | #define __NR_times 43
104 | #define __NR_prof 44
105 | #define __NR_brk 45
106 | #define __NR_setgid 46
107 | #define __NR_getgid 47
108 | #define __NR_signal 48
109 | #define __NR_geteuid 49
110 | #define __NR_getegid 50
111 | #define __NR_acct 51
112 | #define __NR_phys 52
113 | #define __NR_lock 53
114 | #define __NR_ioctl 54
115 | #define __NR_fcntl 55
116 | #define __NR_mpx 56
117 | #define __NR_setpgid 57
118 | #define __NR_ulimit 58
119 | #define __NR_uname 59
120 | #define __NR_umask 60
121 | #define __NR_chroot 61
122 | #define __NR_ustat 62
123 | #define __NR_dup2 63
124 | #define __NR_getppid 64
125 | #define __NR_getpgrp 65
126 | #define __NR_setsid 66
127 | #define __NR_sigaction 67
128 | #define __NR_sgetmask 68
129 | #define __NR_ssetmask 69
130 | #define __NR_setreuid 70
131 | #define __NR_setregid 71
132 | #define __NR_iam 72
133 | #define __NR_whoami 73
134 |
135 | #define _syscall0(type,name) \
136 | type name(void) \
137 | { \
138 | long __res; \
139 | __asm__ volatile ("int $0x80" \
140 | : "=a" (__res) \
141 | : "0" (__NR_##name)); \
142 | if (__res >= 0) \
143 | return (type) __res; \
144 | errno = -__res; \
145 | return -1; \
146 | }
147 |
148 | #define _syscall1(type,name,atype,a) \
149 | type name(atype a) \
150 | { \
151 | long __res; \
152 | __asm__ volatile ("int $0x80" \
153 | : "=a" (__res) \
154 | : "0" (__NR_##name),"b" ((long)(a))); \
155 | if (__res >= 0) \
156 | return (type) __res; \
157 | errno = -__res; \
158 | return -1; \
159 | }
160 |
161 | #define _syscall2(type,name,atype,a,btype,b) \
162 | type name(atype a,btype b) \
163 | { \
164 | long __res; \
165 | __asm__ volatile ("int $0x80" \
166 | : "=a" (__res) \
167 | : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
168 | if (__res >= 0) \
169 | return (type) __res; \
170 | errno = -__res; \
171 | return -1; \
172 | }
173 |
174 | #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
175 | type name(atype a,btype b,ctype c) \
176 | { \
177 | long __res; \
178 | __asm__ volatile ("int $0x80" \
179 | : "=a" (__res) \
180 | : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
181 | if (__res>=0) \
182 | return (type) __res; \
183 | errno=-__res; \
184 | return -1; \
185 | }
186 |
187 | #endif /* __LIBRARY__ */
188 |
189 | extern int errno;
190 |
191 | int access(const char * filename, mode_t mode);
192 | int acct(const char * filename);
193 | int alarm(int sec);
194 | int brk(void * end_data_segment);
195 | void * sbrk(ptrdiff_t increment);
196 | int chdir(const char * filename);
197 | int chmod(const char * filename, mode_t mode);
198 | int chown(const char * filename, uid_t owner, gid_t group);
199 | int chroot(const char * filename);
200 | int close(int fildes);
201 | int creat(const char * filename, mode_t mode);
202 | int dup(int fildes);
203 | int execve(const char * filename, char ** argv, char ** envp);
204 | int execv(const char * pathname, char ** argv);
205 | int execvp(const char * file, char ** argv);
206 | int execl(const char * pathname, char * arg0, ...);
207 | int execlp(const char * file, char * arg0, ...);
208 | int execle(const char * pathname, char * arg0, ...);
209 | volatile void exit(int status);
210 | volatile void _exit(int status);
211 | int fcntl(int fildes, int cmd, ...);
212 | int fork(void);
213 | int getpid(void);
214 | int getuid(void);
215 | int geteuid(void);
216 | int getgid(void);
217 | int getegid(void);
218 | int ioctl(int fildes, int cmd, ...);
219 | int kill(pid_t pid, int signal);
220 | int link(const char * filename1, const char * filename2);
221 | int lseek(int fildes, off_t offset, int origin);
222 | int mknod(const char * filename, mode_t mode, dev_t dev);
223 | int mount(const char * specialfile, const char * dir, int rwflag);
224 | int nice(int val);
225 | int open(const char * filename, int flag, ...);
226 | int pause(void);
227 | int pipe(int * fildes);
228 | int read(int fildes, char * buf, off_t count);
229 | int setpgrp(void);
230 | int setpgid(pid_t pid,pid_t pgid);
231 | int setuid(uid_t uid);
232 | int setgid(gid_t gid);
233 | void (*signal(int sig, void (*fn)(int)))(int);
234 | int stat(const char * filename, struct stat * stat_buf);
235 | int fstat(int fildes, struct stat * stat_buf);
236 | int stime(time_t * tptr);
237 | int sync(void);
238 | time_t time(time_t * tloc);
239 | time_t times(struct tms * tbuf);
240 | int ulimit(int cmd, long limit);
241 | mode_t umask(mode_t mask);
242 | int umount(const char * specialfile);
243 | int uname(struct utsname * name);
244 | int unlink(const char * filename);
245 | int ustat(dev_t dev, struct ustat * ubuf);
246 | int utime(const char * filename, struct utimbuf * times);
247 | pid_t waitpid(pid_t pid,int * wait_stat,int options);
248 | pid_t wait(int * wait_stat);
249 | int write(int fildes, const char * buf, off_t count);
250 | int dup2(int oldfd, int newfd);
251 | int getppid(void);
252 | pid_t getpgrp(void);
253 | pid_t setsid(void);
254 |
255 | #endif
256 |
--------------------------------------------------------------------------------
/lab5/unistd.h:
--------------------------------------------------------------------------------
1 | #ifndef _UNISTD_H
2 | #define _UNISTD_H
3 |
4 | /* ok, this may be a joke, but I'm working on it */
5 | #define _POSIX_VERSION 198808L
6 |
7 | #define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
8 | #define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */
9 | #define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
10 | /*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
11 | /*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
12 |
13 | #define STDIN_FILENO 0
14 | #define STDOUT_FILENO 1
15 | #define STDERR_FILENO 2
16 |
17 | #ifndef NULL
18 | #define NULL ((void *)0)
19 | #endif
20 |
21 | /* access */
22 | #define F_OK 0
23 | #define X_OK 1
24 | #define W_OK 2
25 | #define R_OK 4
26 |
27 | /* lseek */
28 | #define SEEK_SET 0
29 | #define SEEK_CUR 1
30 | #define SEEK_END 2
31 |
32 | /* _SC stands for System Configuration. We don't use them much */
33 | #define _SC_ARG_MAX 1
34 | #define _SC_CHILD_MAX 2
35 | #define _SC_CLOCKS_PER_SEC 3
36 | #define _SC_NGROUPS_MAX 4
37 | #define _SC_OPEN_MAX 5
38 | #define _SC_JOB_CONTROL 6
39 | #define _SC_SAVED_IDS 7
40 | #define _SC_VERSION 8
41 |
42 | /* more (possibly) configurable things - now pathnames */
43 | #define _PC_LINK_MAX 1
44 | #define _PC_MAX_CANON 2
45 | #define _PC_MAX_INPUT 3
46 | #define _PC_NAME_MAX 4
47 | #define _PC_PATH_MAX 5
48 | #define _PC_PIPE_BUF 6
49 | #define _PC_NO_TRUNC 7
50 | #define _PC_VDISABLE 8
51 | #define _PC_CHOWN_RESTRICTED 9
52 |
53 | #include
54 | #include
55 | #include
56 | #include
57 |
58 | #ifdef __LIBRARY__
59 |
60 | #define __NR_setup 0 /* used only by init, to get system going */
61 | #define __NR_exit 1
62 | #define __NR_fork 2
63 | #define __NR_read 3
64 | #define __NR_write 4
65 | #define __NR_open 5
66 | #define __NR_close 6
67 | #define __NR_waitpid 7
68 | #define __NR_creat 8
69 | #define __NR_link 9
70 | #define __NR_unlink 10
71 | #define __NR_execve 11
72 | #define __NR_chdir 12
73 | #define __NR_time 13
74 | #define __NR_mknod 14
75 | #define __NR_chmod 15
76 | #define __NR_chown 16
77 | #define __NR_break 17
78 | #define __NR_stat 18
79 | #define __NR_lseek 19
80 | #define __NR_getpid 20
81 | #define __NR_mount 21
82 | #define __NR_umount 22
83 | #define __NR_setuid 23
84 | #define __NR_getuid 24
85 | #define __NR_stime 25
86 | #define __NR_ptrace 26
87 | #define __NR_alarm 27
88 | #define __NR_fstat 28
89 | #define __NR_pause 29
90 | #define __NR_utime 30
91 | #define __NR_stty 31
92 | #define __NR_gtty 32
93 | #define __NR_access 33
94 | #define __NR_nice 34
95 | #define __NR_ftime 35
96 | #define __NR_sync 36
97 | #define __NR_kill 37
98 | #define __NR_rename 38
99 | #define __NR_mkdir 39
100 | #define __NR_rmdir 40
101 | #define __NR_dup 41
102 | #define __NR_pipe 42
103 | #define __NR_times 43
104 | #define __NR_prof 44
105 | #define __NR_brk 45
106 | #define __NR_setgid 46
107 | #define __NR_getgid 47
108 | #define __NR_signal 48
109 | #define __NR_geteuid 49
110 | #define __NR_getegid 50
111 | #define __NR_acct 51
112 | #define __NR_phys 52
113 | #define __NR_lock 53
114 | #define __NR_ioctl 54
115 | #define __NR_fcntl 55
116 | #define __NR_mpx 56
117 | #define __NR_setpgid 57
118 | #define __NR_ulimit 58
119 | #define __NR_uname 59
120 | #define __NR_umask 60
121 | #define __NR_chroot 61
122 | #define __NR_ustat 62
123 | #define __NR_dup2 63
124 | #define __NR_getppid 64
125 | #define __NR_getpgrp 65
126 | #define __NR_setsid 66
127 | #define __NR_sigaction 67
128 | #define __NR_sgetmask 68
129 | #define __NR_ssetmask 69
130 | #define __NR_setreuid 70
131 | #define __NR_setregid 71
132 | #define __NR_sem_open 72
133 | #define __NR_sem_wait 73
134 | #define __NR_sem_post 74
135 | #define __NR_sem_unlink 75
136 |
137 | #define QUE_LEN 16
138 | #define SEM_FAILED (void*) 0
139 | struct semaphore_queue
140 | {
141 | int front;
142 | int rear;
143 | struct task_struct *wait_tasks[QUE_LEN];
144 | };
145 | typedef struct semaphore_queue sem_queue;
146 |
147 | struct semaphore_t
148 | {
149 | int value;
150 | int occupied;
151 | char name[16];
152 | struct semaphore_queue wait_queue;
153 | };
154 | typedef struct semaphore_t sem_t;
155 |
156 | #define _syscall0(type,name) \
157 | type name(void) \
158 | { \
159 | long __res; \
160 | __asm__ volatile ("int $0x80" \
161 | : "=a" (__res) \
162 | : "0" (__NR_##name)); \
163 | if (__res >= 0) \
164 | return (type) __res; \
165 | errno = -__res; \
166 | return -1; \
167 | }
168 |
169 | #define _syscall1(type,name,atype,a) \
170 | type name(atype a) \
171 | { \
172 | long __res; \
173 | __asm__ volatile ("int $0x80" \
174 | : "=a" (__res) \
175 | : "0" (__NR_##name),"b" ((long)(a))); \
176 | if (__res >= 0) \
177 | return (type) __res; \
178 | errno = -__res; \
179 | return -1; \
180 | }
181 |
182 | #define _syscall2(type,name,atype,a,btype,b) \
183 | type name(atype a,btype b) \
184 | { \
185 | long __res; \
186 | __asm__ volatile ("int $0x80" \
187 | : "=a" (__res) \
188 | : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
189 | if (__res >= 0) \
190 | return (type) __res; \
191 | errno = -__res; \
192 | return -1; \
193 | }
194 |
195 | #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
196 | type name(atype a,btype b,ctype c) \
197 | { \
198 | long __res; \
199 | __asm__ volatile ("int $0x80" \
200 | : "=a" (__res) \
201 | : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
202 | if (__res>=0) \
203 | return (type) __res; \
204 | errno=-__res; \
205 | return -1; \
206 | }
207 |
208 | #endif /* __LIBRARY__ */
209 |
210 | extern int errno;
211 |
212 | int access(const char * filename, mode_t mode);
213 | int acct(const char * filename);
214 | int alarm(int sec);
215 | int brk(void * end_data_segment);
216 | void * sbrk(ptrdiff_t increment);
217 | int chdir(const char * filename);
218 | int chmod(const char * filename, mode_t mode);
219 | int chown(const char * filename, uid_t owner, gid_t group);
220 | int chroot(const char * filename);
221 | int close(int fildes);
222 | int creat(const char * filename, mode_t mode);
223 | int dup(int fildes);
224 | int execve(const char * filename, char ** argv, char ** envp);
225 | int execv(const char * pathname, char ** argv);
226 | int execvp(const char * file, char ** argv);
227 | int execl(const char * pathname, char * arg0, ...);
228 | int execlp(const char * file, char * arg0, ...);
229 | int execle(const char * pathname, char * arg0, ...);
230 | volatile void exit(int status);
231 | volatile void _exit(int status);
232 | int fcntl(int fildes, int cmd, ...);
233 | int fork(void);
234 | int getpid(void);
235 | int getuid(void);
236 | int geteuid(void);
237 | int getgid(void);
238 | int getegid(void);
239 | int ioctl(int fildes, int cmd, ...);
240 | int kill(pid_t pid, int signal);
241 | int link(const char * filename1, const char * filename2);
242 | int lseek(int fildes, off_t offset, int origin);
243 | int mknod(const char * filename, mode_t mode, dev_t dev);
244 | int mount(const char * specialfile, const char * dir, int rwflag);
245 | int nice(int val);
246 | int open(const char * filename, int flag, ...);
247 | int pause(void);
248 | int pipe(int * fildes);
249 | int read(int fildes, char * buf, off_t count);
250 | int setpgrp(void);
251 | int setpgid(pid_t pid,pid_t pgid);
252 | int setuid(uid_t uid);
253 | int setgid(gid_t gid);
254 | void (*signal(int sig, void (*fn)(int)))(int);
255 | int stat(const char * filename, struct stat * stat_buf);
256 | int fstat(int fildes, struct stat * stat_buf);
257 | int stime(time_t * tptr);
258 | int sync(void);
259 | time_t time(time_t * tloc);
260 | time_t times(struct tms * tbuf);
261 | int ulimit(int cmd, long limit);
262 | mode_t umask(mode_t mask);
263 | int umount(const char * specialfile);
264 | int uname(struct utsname * name);
265 | int unlink(const char * filename);
266 | int ustat(dev_t dev, struct ustat * ubuf);
267 | int utime(const char * filename, struct utimbuf * times);
268 | pid_t waitpid(pid_t pid,int * wait_stat,int options);
269 | pid_t wait(int * wait_stat);
270 | int write(int fildes, const char * buf, off_t count);
271 | int dup2(int oldfd, int newfd);
272 | int getppid(void);
273 | pid_t getpgrp(void);
274 | pid_t setsid(void);
275 |
276 | #endif
277 |
--------------------------------------------------------------------------------
/lab6/unistd.h:
--------------------------------------------------------------------------------
1 | #ifndef _UNISTD_H
2 | #define _UNISTD_H
3 |
4 | /* ok, this may be a joke, but I'm working on it */
5 | #define _POSIX_VERSION 198808L
6 |
7 | #define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
8 | #define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */
9 | #define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
10 | /*#define _POSIX_SAVED_IDS */ /* we'll get to this yet */
11 | /*#define _POSIX_JOB_CONTROL */ /* we aren't there quite yet. Soon hopefully */
12 |
13 | #define STDIN_FILENO 0
14 | #define STDOUT_FILENO 1
15 | #define STDERR_FILENO 2
16 |
17 | #ifndef NULL
18 | #define NULL ((void *)0)
19 | #endif
20 |
21 | /* access */
22 | #define F_OK 0
23 | #define X_OK 1
24 | #define W_OK 2
25 | #define R_OK 4
26 |
27 | /* lseek */
28 | #define SEEK_SET 0
29 | #define SEEK_CUR 1
30 | #define SEEK_END 2
31 |
32 | /* _SC stands for System Configuration. We don't use them much */
33 | #define _SC_ARG_MAX 1
34 | #define _SC_CHILD_MAX 2
35 | #define _SC_CLOCKS_PER_SEC 3
36 | #define _SC_NGROUPS_MAX 4
37 | #define _SC_OPEN_MAX 5
38 | #define _SC_JOB_CONTROL 6
39 | #define _SC_SAVED_IDS 7
40 | #define _SC_VERSION 8
41 |
42 | /* more (possibly) configurable things - now pathnames */
43 | #define _PC_LINK_MAX 1
44 | #define _PC_MAX_CANON 2
45 | #define _PC_MAX_INPUT 3
46 | #define _PC_NAME_MAX 4
47 | #define _PC_PATH_MAX 5
48 | #define _PC_PIPE_BUF 6
49 | #define _PC_NO_TRUNC 7
50 | #define _PC_VDISABLE 8
51 | #define _PC_CHOWN_RESTRICTED 9
52 |
53 | #include
54 | #include
55 | #include
56 | #include
57 |
58 | #ifdef __LIBRARY__
59 |
60 | #define __NR_setup 0 /* used only by init, to get system going */
61 | #define __NR_exit 1
62 | #define __NR_fork 2
63 | #define __NR_read 3
64 | #define __NR_write 4
65 | #define __NR_open 5
66 | #define __NR_close 6
67 | #define __NR_waitpid 7
68 | #define __NR_creat 8
69 | #define __NR_link 9
70 | #define __NR_unlink 10
71 | #define __NR_execve 11
72 | #define __NR_chdir 12
73 | #define __NR_time 13
74 | #define __NR_mknod 14
75 | #define __NR_chmod 15
76 | #define __NR_chown 16
77 | #define __NR_break 17
78 | #define __NR_stat 18
79 | #define __NR_lseek 19
80 | #define __NR_getpid 20
81 | #define __NR_mount 21
82 | #define __NR_umount 22
83 | #define __NR_setuid 23
84 | #define __NR_getuid 24
85 | #define __NR_stime 25
86 | #define __NR_ptrace 26
87 | #define __NR_alarm 27
88 | #define __NR_fstat 28
89 | #define __NR_pause 29
90 | #define __NR_utime 30
91 | #define __NR_stty 31
92 | #define __NR_gtty 32
93 | #define __NR_access 33
94 | #define __NR_nice 34
95 | #define __NR_ftime 35
96 | #define __NR_sync 36
97 | #define __NR_kill 37
98 | #define __NR_rename 38
99 | #define __NR_mkdir 39
100 | #define __NR_rmdir 40
101 | #define __NR_dup 41
102 | #define __NR_pipe 42
103 | #define __NR_times 43
104 | #define __NR_prof 44
105 | #define __NR_brk 45
106 | #define __NR_setgid 46
107 | #define __NR_getgid 47
108 | #define __NR_signal 48
109 | #define __NR_geteuid 49
110 | #define __NR_getegid 50
111 | #define __NR_acct 51
112 | #define __NR_phys 52
113 | #define __NR_lock 53
114 | #define __NR_ioctl 54
115 | #define __NR_fcntl 55
116 | #define __NR_mpx 56
117 | #define __NR_setpgid 57
118 | #define __NR_ulimit 58
119 | #define __NR_uname 59
120 | #define __NR_umask 60
121 | #define __NR_chroot 61
122 | #define __NR_ustat 62
123 | #define __NR_dup2 63
124 | #define __NR_getppid 64
125 | #define __NR_getpgrp 65
126 | #define __NR_setsid 66
127 | #define __NR_sigaction 67
128 | #define __NR_sgetmask 68
129 | #define __NR_ssetmask 69
130 | #define __NR_setreuid 70
131 | #define __NR_setregid 71
132 | #define __NR_sem_open 72
133 | #define __NR_sem_wait 73
134 | #define __NR_sem_post 74
135 | #define __NR_sem_unlink 75
136 | #define __NR_shmget 76
137 | #define __NR_shmat 77
138 |
139 | #define QUE_LEN 16
140 | #define SEM_FAILED (void*) 0
141 | struct semaphore_queue
142 | {
143 | int front;
144 | int rear;
145 | struct task_struct *wait_tasks[QUE_LEN];
146 | };
147 | typedef struct semaphore_queue sem_queue;
148 |
149 | struct semaphore_t
150 | {
151 | int value;
152 | int occupied;
153 | char name[16];
154 | struct semaphore_queue wait_queue;
155 | };
156 | typedef struct semaphore_t sem_t;
157 |
158 | #define _syscall0(type,name) \
159 | type name(void) \
160 | { \
161 | long __res; \
162 | __asm__ volatile ("int $0x80" \
163 | : "=a" (__res) \
164 | : "0" (__NR_##name)); \
165 | if (__res >= 0) \
166 | return (type) __res; \
167 | errno = -__res; \
168 | return -1; \
169 | }
170 |
171 | #define _syscall1(type,name,atype,a) \
172 | type name(atype a) \
173 | { \
174 | long __res; \
175 | __asm__ volatile ("int $0x80" \
176 | : "=a" (__res) \
177 | : "0" (__NR_##name),"b" ((long)(a))); \
178 | if (__res >= 0) \
179 | return (type) __res; \
180 | errno = -__res; \
181 | return -1; \
182 | }
183 |
184 | #define _syscall2(type,name,atype,a,btype,b) \
185 | type name(atype a,btype b) \
186 | { \
187 | long __res; \
188 | __asm__ volatile ("int $0x80" \
189 | : "=a" (__res) \
190 | : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
191 | if (__res >= 0) \
192 | return (type) __res; \
193 | errno = -__res; \
194 | return -1; \
195 | }
196 |
197 | #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
198 | type name(atype a,btype b,ctype c) \
199 | { \
200 | long __res; \
201 | __asm__ volatile ("int $0x80" \
202 | : "=a" (__res) \
203 | : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
204 | if (__res>=0) \
205 | return (type) __res; \
206 | errno=-__res; \
207 | return -1; \
208 | }
209 |
210 | #endif /* __LIBRARY__ */
211 |
212 | extern int errno;
213 |
214 | int access(const char * filename, mode_t mode);
215 | int acct(const char * filename);
216 | int alarm(int sec);
217 | int brk(void * end_data_segment);
218 | void * sbrk(ptrdiff_t increment);
219 | int chdir(const char * filename);
220 | int chmod(const char * filename, mode_t mode);
221 | int chown(const char * filename, uid_t owner, gid_t group);
222 | int chroot(const char * filename);
223 | int close(int fildes);
224 | int creat(const char * filename, mode_t mode);
225 | int dup(int fildes);
226 | int execve(const char * filename, char ** argv, char ** envp);
227 | int execv(const char * pathname, char ** argv);
228 | int execvp(const char * file, char ** argv);
229 | int execl(const char * pathname, char * arg0, ...);
230 | int execlp(const char * file, char * arg0, ...);
231 | int execle(const char * pathname, char * arg0, ...);
232 | volatile void exit(int status);
233 | volatile void _exit(int status);
234 | int fcntl(int fildes, int cmd, ...);
235 | int fork(void);
236 | int getpid(void);
237 | int getuid(void);
238 | int geteuid(void);
239 | int getgid(void);
240 | int getegid(void);
241 | int ioctl(int fildes, int cmd, ...);
242 | int kill(pid_t pid, int signal);
243 | int link(const char * filename1, const char * filename2);
244 | int lseek(int fildes, off_t offset, int origin);
245 | int mknod(const char * filename, mode_t mode, dev_t dev);
246 | int mount(const char * specialfile, const char * dir, int rwflag);
247 | int nice(int val);
248 | int open(const char * filename, int flag, ...);
249 | int pause(void);
250 | int pipe(int * fildes);
251 | int read(int fildes, char * buf, off_t count);
252 | int setpgrp(void);
253 | int setpgid(pid_t pid,pid_t pgid);
254 | int setuid(uid_t uid);
255 | int setgid(gid_t gid);
256 | void (*signal(int sig, void (*fn)(int)))(int);
257 | int stat(const char * filename, struct stat * stat_buf);
258 | int fstat(int fildes, struct stat * stat_buf);
259 | int stime(time_t * tptr);
260 | int sync(void);
261 | time_t time(time_t * tloc);
262 | time_t times(struct tms * tbuf);
263 | int ulimit(int cmd, long limit);
264 | mode_t umask(mode_t mask);
265 | int umount(const char * specialfile);
266 | int uname(struct utsname * name);
267 | int unlink(const char * filename);
268 | int ustat(dev_t dev, struct ustat * ubuf);
269 | int utime(const char * filename, struct utimbuf * times);
270 | pid_t waitpid(pid_t pid,int * wait_stat,int options);
271 | pid_t wait(int * wait_stat);
272 | int write(int fildes, const char * buf, off_t count);
273 | int dup2(int oldfd, int newfd);
274 | int getppid(void);
275 | pid_t getpgrp(void);
276 | pid_t setsid(void);
277 |
278 | #endif
279 |
--------------------------------------------------------------------------------
/lab7/tty_io.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/tty_io.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
9 | * or rs-channels. It also implements echoing, cooked mode etc.
10 | *
11 | * Kill-line thanks to John T Kohl.
12 | */
13 | #include
14 | #include
15 | #include
16 |
17 | #define ALRMMASK (1<<(SIGALRM-1))
18 | #define KILLMASK (1<<(SIGKILL-1))
19 | #define INTMASK (1<<(SIGINT-1))
20 | #define QUITMASK (1<<(SIGQUIT-1))
21 | #define TSTPMASK (1<<(SIGTSTP-1))
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
29 | #define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
30 | #define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
31 |
32 | #define L_CANON(tty) _L_FLAG((tty),ICANON)
33 | #define L_ISIG(tty) _L_FLAG((tty),ISIG)
34 | #define L_ECHO(tty) _L_FLAG((tty),ECHO)
35 | #define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
36 | #define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
37 | #define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
38 | #define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
39 |
40 | #define I_UCLC(tty) _I_FLAG((tty),IUCLC)
41 | #define I_NLCR(tty) _I_FLAG((tty),INLCR)
42 | #define I_CRNL(tty) _I_FLAG((tty),ICRNL)
43 | #define I_NOCR(tty) _I_FLAG((tty),IGNCR)
44 |
45 | #define O_POST(tty) _O_FLAG((tty),OPOST)
46 | #define O_NLCR(tty) _O_FLAG((tty),ONLCR)
47 | #define O_CRNL(tty) _O_FLAG((tty),OCRNL)
48 | #define O_NLRET(tty) _O_FLAG((tty),ONLRET)
49 | #define O_LCUC(tty) _O_FLAG((tty),OLCUC)
50 |
51 | struct tty_struct tty_table[] = {
52 | {
53 | {ICRNL, /* change incoming CR to NL */
54 | OPOST|ONLCR, /* change outgoing NL to CRNL */
55 | 0,
56 | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
57 | 0, /* console termio */
58 | INIT_C_CC},
59 | 0, /* initial pgrp */
60 | 0, /* initial stopped */
61 | con_write,
62 | {0,0,0,0,""}, /* console read-queue */
63 | {0,0,0,0,""}, /* console write-queue */
64 | {0,0,0,0,""} /* console secondary queue */
65 | },{
66 | {0, /* no translation */
67 | 0, /* no translation */
68 | B2400 | CS8,
69 | 0,
70 | 0,
71 | INIT_C_CC},
72 | 0,
73 | 0,
74 | rs_write,
75 | {0x3f8,0,0,0,""}, /* rs 1 */
76 | {0x3f8,0,0,0,""},
77 | {0,0,0,0,""}
78 | },{
79 | {0, /* no translation */
80 | 0, /* no translation */
81 | B2400 | CS8,
82 | 0,
83 | 0,
84 | INIT_C_CC},
85 | 0,
86 | 0,
87 | rs_write,
88 | {0x2f8,0,0,0,""}, /* rs 2 */
89 | {0x2f8,0,0,0,""},
90 | {0,0,0,0,""}
91 | }
92 | };
93 |
94 | /*
95 | * these are the tables used by the machine code handlers.
96 | * you can implement pseudo-tty's or something by changing
97 | * them. Currently not done.
98 | */
99 | struct tty_queue * table_list[]={
100 | &tty_table[0].read_q, &tty_table[0].write_q,
101 | &tty_table[1].read_q, &tty_table[1].write_q,
102 | &tty_table[2].read_q, &tty_table[2].write_q
103 | };
104 |
105 | void tty_init(void)
106 | {
107 | rs_init();
108 | con_init();
109 | }
110 |
111 | void tty_intr(struct tty_struct * tty, int mask)
112 | {
113 | int i;
114 |
115 | if (tty->pgrp <= 0)
116 | return;
117 | for (i=0;ipgrp==tty->pgrp)
119 | task[i]->signal |= mask;
120 | }
121 |
122 | static void sleep_if_empty(struct tty_queue * queue)
123 | {
124 | cli();
125 | while (!current->signal && EMPTY(*queue))
126 | interruptible_sleep_on(&queue->proc_list);
127 | sti();
128 | }
129 |
130 | static void sleep_if_full(struct tty_queue * queue)
131 | {
132 | if (!FULL(*queue))
133 | return;
134 | cli();
135 | while (!current->signal && LEFT(*queue)<128)
136 | interruptible_sleep_on(&queue->proc_list);
137 | sti();
138 | }
139 |
140 | void wait_for_keypress(void)
141 | {
142 | sleep_if_empty(&tty_table[0].secondary);
143 | }
144 |
145 | int judge=-1;
146 | int f1=0,f2=0,f3=0;
147 |
148 | void copy_to_cooked(struct tty_struct * tty)
149 | {
150 | signed char c;
151 |
152 | while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
153 | GETCH(tty->read_q,c);
154 | if(c==27)
155 | f1=1;
156 | else if(f1==1&&f2==0&&c==91)
157 | f2=1;
158 | else if(f1==1&&f2==1&&c==91)
159 | f3=1;
160 | else if(f1==1&&f2==1&&f3==1&&c==76)
161 | {
162 | judge*=-1;
163 | continue;
164 | }
165 | else
166 | f1=f2=f3=0;
167 |
168 | if (c==13)
169 | if (I_CRNL(tty))
170 | c=10;
171 | else if (I_NOCR(tty))
172 | continue;
173 | else ;
174 | else if (c==10 && I_NLCR(tty))
175 | c=13;
176 | if (I_UCLC(tty))
177 | c=tolower(c);
178 | if (L_CANON(tty)) {
179 | if (c==KILL_CHAR(tty)) {
180 | /* deal with killing the input line */
181 | while(!(EMPTY(tty->secondary) ||
182 | (c=LAST(tty->secondary))==10 ||
183 | c==EOF_CHAR(tty))) {
184 | if (L_ECHO(tty)) {
185 | if (c<32)
186 | PUTCH(127,tty->write_q);
187 | PUTCH(127,tty->write_q);
188 | tty->write(tty);
189 | }
190 | DEC(tty->secondary.head);
191 | }
192 | continue;
193 | }
194 | if (c==ERASE_CHAR(tty)) {
195 | if (EMPTY(tty->secondary) ||
196 | (c=LAST(tty->secondary))==10 ||
197 | c==EOF_CHAR(tty))
198 | continue;
199 | if (L_ECHO(tty)) {
200 | if (c<32)
201 | PUTCH(127,tty->write_q);
202 | PUTCH(127,tty->write_q);
203 | tty->write(tty);
204 | }
205 | DEC(tty->secondary.head);
206 | continue;
207 | }
208 | if (c==STOP_CHAR(tty)) {
209 | tty->stopped=1;
210 | continue;
211 | }
212 | if (c==START_CHAR(tty)) {
213 | tty->stopped=0;
214 | continue;
215 | }
216 | }
217 | if (L_ISIG(tty)) {
218 | if (c==INTR_CHAR(tty)) {
219 | tty_intr(tty,INTMASK);
220 | continue;
221 | }
222 | if (c==QUIT_CHAR(tty)) {
223 | tty_intr(tty,QUITMASK);
224 | continue;
225 | }
226 | }
227 | if (c==10 || c==EOF_CHAR(tty))
228 | tty->secondary.data++;
229 | if (L_ECHO(tty)) {
230 | if (c==10) {
231 | PUTCH(10,tty->write_q);
232 | PUTCH(13,tty->write_q);
233 | } else if (c<32) {
234 | if (L_ECHOCTL(tty)) {
235 | PUTCH('^',tty->write_q);
236 | PUTCH(c+64,tty->write_q);
237 | }
238 | } else
239 | PUTCH(c,tty->write_q);
240 | tty->write(tty);
241 | }
242 | PUTCH(c,tty->secondary);
243 | }
244 | wake_up(&tty->secondary.proc_list);
245 | }
246 |
247 | int tty_read(unsigned channel, char * buf, int nr)
248 | {
249 | struct tty_struct * tty;
250 | char c, * b=buf;
251 | int minimum,time,flag=0;
252 | long oldalarm;
253 |
254 | if (channel>2 || nr<0) return -1;
255 | tty = &tty_table[channel];
256 | oldalarm = current->alarm;
257 | time = 10L*tty->termios.c_cc[VTIME];
258 | minimum = tty->termios.c_cc[VMIN];
259 | if (time && !minimum) {
260 | minimum=1;
261 | if ((flag=(!oldalarm || time+jiffiesalarm = time+jiffies;
263 | }
264 | if (minimum>nr)
265 | minimum=nr;
266 | while (nr>0) {
267 | if (flag && (current->signal & ALRMMASK)) {
268 | current->signal &= ~ALRMMASK;
269 | break;
270 | }
271 | if (current->signal)
272 | break;
273 | if (EMPTY(tty->secondary) || (L_CANON(tty) &&
274 | !tty->secondary.data && LEFT(tty->secondary)>20)) {
275 | sleep_if_empty(&tty->secondary);
276 | continue;
277 | }
278 | do {
279 | GETCH(tty->secondary,c);
280 | if (c==EOF_CHAR(tty) || c==10)
281 | tty->secondary.data--;
282 | if (c==EOF_CHAR(tty) && L_CANON(tty))
283 | return (b-buf);
284 | else {
285 | put_fs_byte(c,b++);
286 | if (!--nr)
287 | break;
288 | }
289 | } while (nr>0 && !EMPTY(tty->secondary));
290 | if (time && !L_CANON(tty)) {
291 | if ((flag=(!oldalarm || time+jiffiesalarm = time+jiffies;
293 | else
294 | current->alarm = oldalarm;
295 | }
296 | if (L_CANON(tty)) {
297 | if (b-buf)
298 | break;
299 | } else if (b-buf >= minimum)
300 | break;
301 | }
302 | current->alarm = oldalarm;
303 | if (current->signal && !(b-buf))
304 | return -EINTR;
305 | return (b-buf);
306 | }
307 |
308 | int tty_write(unsigned channel, char * buf, int nr)
309 | {
310 | static int cr_flag=0;
311 | struct tty_struct * tty;
312 | char c, *b=buf;
313 |
314 | if (channel>2 || nr<0) return -1;
315 | tty = channel + tty_table;
316 | while (nr>0) {
317 | sleep_if_full(&tty->write_q);
318 | if (current->signal)
319 | break;
320 | while (nr>0 && !FULL(tty->write_q)) {
321 | c=get_fs_byte(b);
322 | if (O_POST(tty)) {
323 | if (c=='\r' && O_CRNL(tty))
324 | c='\n';
325 | else if (c=='\n' && O_NLRET(tty))
326 | c='\r';
327 | if (c=='\n' && !cr_flag && O_NLCR(tty)) {
328 | cr_flag = 1;
329 | PUTCH(13,tty->write_q);
330 | continue;
331 | }
332 | if (O_LCUC(tty))
333 | c=toupper(c);
334 | }
335 | b++; nr--;
336 | cr_flag = 0;
337 | PUTCH(c,tty->write_q);
338 | }
339 | tty->write(tty);
340 | if (nr>0)
341 | schedule();
342 | }
343 | return (b-buf);
344 | }
345 |
346 | /*
347 | * Jeh, sometimes I really like the 386.
348 | * This routine is called from an interrupt,
349 | * and there should be absolutely no problem
350 | * with sleeping even in an interrupt (I hope).
351 | * Of course, if somebody proves me wrong, I'll
352 | * hate intel for all time :-). We'll have to
353 | * be careful and see to reinstating the interrupt
354 | * chips before calling this, though.
355 | *
356 | * I don't think we sleep here under normal circumstances
357 | * anyway, which is good, as the task sleeping might be
358 | * totally innocent.
359 | */
360 | void do_tty_interrupt(int tty)
361 | {
362 | copy_to_cooked(tty_table+tty);
363 | }
364 |
365 | void chr_dev_init(void)
366 | {
367 | }
368 |
--------------------------------------------------------------------------------
/lab3/stat_log.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import sys
3 | import copy
4 |
5 | P_NULL = 0
6 | P_NEW = 1
7 | P_READY = 2
8 | P_RUNNING = 4
9 | P_WAITING = 8
10 | P_EXIT = 16
11 |
12 | S_STATE = 0
13 | S_TIME = 1
14 |
15 | HZ = 100
16 |
17 | graph_title = r"""
18 | -----===< COOL GRAPHIC OF SCHEDULER >===-----
19 | [Symbol] [Meaning]
20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 | number PID or tick
22 | "-" New or Exit
23 | "#" Running
24 | "|" Ready
25 | ":" Waiting
26 | / Running with
27 | "+" -| Ready
28 | \and/or Waiting
29 | -----===< !!!!!!!!!!!!!!!!!!!!!!!!! >===-----
30 | """
31 |
32 | usage = """
33 | Usage:
34 | %s /path/to/process.log [PID1] [PID2] ... [-x PID1 [PID2] ... ] [-m] [-g]
35 | Example:
36 | # Include process 6, 7, 8 and 9 in statistics only. (Unit: tick)
37 | %s /path/to/process.log 6 7 8 9
38 | # Exclude process 0 and 1 from statistics. (Unit: tick)
39 | %s /path/to/process.log -x 0 1
40 | # Include process 6 and 7 only and print a COOL "graphic"! (Unit: millisecond)
41 | %s /path/to/process.log 6 7 -m -g
42 | # Include all processes and print a COOL "graphic"! (Unit: tick)
43 | %s /path/to/process.log -g
44 | """
45 |
46 | class MyError(Exception):
47 | pass
48 |
49 | class DuplicateNew(MyError):
50 | def __init__(self, pid):
51 | args = "More than one 'N' for process %d." % pid
52 | MyError.__init__(self, args)
53 |
54 | class UnknownState(MyError):
55 | def __init__(self, state):
56 | args = "Unknown state '%s' found." % state
57 | MyError.__init__(self, args)
58 |
59 | class BadTime(MyError):
60 | def __init__(self, time):
61 | args = "The time '%d' is bad. It should >= previous line's time." % time
62 | MyError.__init__(self, args)
63 |
64 | class TaskHasExited(MyError):
65 | def __init__(self, state):
66 | args = "The process has exited. Why it enter '%s' state again?" % state
67 | MyError.__init__(self, args)
68 |
69 | class BadFormat(MyError):
70 | def __init__(self):
71 | args = "Bad log format"
72 | MyError.__init__(self, args)
73 |
74 | class RepeatState(MyError):
75 | def __init__(self, pid):
76 | args = "Previous state of process %d is identical with this line." % (pid)
77 | MyError.__init__(self, args)
78 |
79 | class SameLine(MyError):
80 | def __init__(self):
81 | args = "It is a clone of previous line."
82 | MyError.__init__(self, args)
83 |
84 | class NoNew(MyError):
85 | def __init__(self, pid, state):
86 | args = "The first state of process %d is '%s'. Why not 'N'?" % (pid, state)
87 | MyError.__init__(self, args)
88 |
89 | class statistics:
90 | def __init__(self, pool, include, exclude):
91 | if include:
92 | self.pool = process_pool()
93 | for process in pool:
94 | if process.getpid() in include:
95 | self.pool.add(process)
96 | else:
97 | self.pool = copy.copy(pool)
98 |
99 | if exclude:
100 | for pid in exclude:
101 | if self.pool.get_process(pid):
102 | self.pool.remove(pid)
103 |
104 | def list_pid(self):
105 | l = []
106 | for process in self.pool:
107 | l.append(process.getpid())
108 | return l
109 |
110 | def average_turnaround(self):
111 | if len(self.pool) == 0:
112 | return 0
113 | sum = 0
114 | for process in self.pool:
115 | sum += process.turnaround_time()
116 | return float(sum) / len(self.pool)
117 |
118 | def average_waiting(self):
119 | if len(self.pool) == 0:
120 | return 0
121 | sum = 0
122 | for process in self.pool:
123 | sum += process.waiting_time()
124 | return float(sum) / len(self.pool)
125 |
126 | def begin_time(self):
127 | begin = 0xEFFFFF
128 | for p in self.pool:
129 | if p.begin_time() < begin:
130 | begin = p.begin_time()
131 | return begin
132 |
133 | def end_time(self):
134 | end = 0
135 | for p in self.pool:
136 | if p.end_time() > end:
137 | end = p.end_time()
138 | return end
139 |
140 | def throughput(self):
141 | return len(self.pool) * HZ / float(self.end_time() - self.begin_time())
142 |
143 | def print_graphic(self):
144 | begin = self.begin_time()
145 | end = self.end_time()
146 |
147 | print graph_title
148 |
149 | for i in range(begin, end+1):
150 | line = "%5d " % i
151 | for p in self.pool:
152 | state = p.get_state(i)
153 | if state & P_NEW:
154 | line += "-"
155 | elif state == P_READY or state == P_READY | P_WAITING:
156 | line += "|"
157 | elif state == P_RUNNING:
158 | line += "#"
159 | elif state == P_WAITING:
160 | line += ":"
161 | elif state & P_EXIT:
162 | line += "-"
163 | elif state == P_NULL:
164 | line += " "
165 | elif state & P_RUNNING:
166 | line += "+"
167 | else:
168 | assert False
169 | if p.get_state(i-1) != state and state != P_NULL:
170 | line += "%-3d" % p.getpid()
171 | else:
172 | line += " "
173 | print line
174 |
175 | class process_pool:
176 | def __init__(self):
177 | self.list = []
178 |
179 | def get_process(self, pid):
180 | for process in self.list:
181 | if process.getpid() == pid:
182 | return process
183 | return None
184 |
185 | def remove(self, pid):
186 | for process in self.list:
187 | if process.getpid() == pid:
188 | self.list.remove(process)
189 |
190 | def new(self, pid, time):
191 | p = self.get_process(pid)
192 | if p:
193 | if pid != 0:
194 | raise DuplicateNew(pid)
195 | else:
196 | p.states=[(P_NEW, time)]
197 | else:
198 | p = process(pid, time)
199 | self.list.append(p)
200 | return p
201 |
202 | def add(self, p):
203 | self.list.append(p)
204 |
205 | def __len__(self):
206 | return len(self.list)
207 |
208 | def __iter__(self):
209 | return iter(self.list)
210 |
211 | class process:
212 | def __init__(self, pid, time):
213 | self.pid = pid
214 | self.states = [(P_NEW, time)]
215 |
216 | def getpid(self):
217 | return self.pid
218 |
219 | def change_state(self, state, time):
220 | last_state, last_time = self.states[-1]
221 | if state == P_NEW:
222 | raise DuplicateNew(pid)
223 | if time < last_time:
224 | raise BadTime(time)
225 | if last_state == P_EXIT:
226 | raise TaskHasExited(state)
227 | if last_state == state and self.pid != 0: # task 0 can have duplicate state
228 | raise RepeatState(self.pid)
229 |
230 | self.states.append((state, time))
231 |
232 | def get_state(self, time):
233 | rval = P_NULL
234 | combo = P_NULL
235 | if self.begin_time() <= time <= self.end_time():
236 | for state, s_time in self.states:
237 | if s_time < time:
238 | rval = state
239 | elif s_time == time:
240 | combo |= state
241 | else:
242 | break
243 | if combo:
244 | rval = combo
245 | return rval
246 |
247 | def turnaround_time(self):
248 | return self.states[-1][S_TIME] - self.states[0][S_TIME]
249 |
250 | def waiting_time(self):
251 | return self.state_last_time(P_READY)
252 |
253 | def cpu_time(self):
254 | return self.state_last_time(P_RUNNING)
255 |
256 | def io_time(self):
257 | return self.state_last_time(P_WAITING)
258 |
259 | def state_last_time(self, state):
260 | time = 0
261 | state_begin = 0
262 | for s,t in self.states:
263 | if s == state:
264 | state_begin = t
265 | elif state_begin != 0:
266 | assert state_begin <= t
267 | time += t - state_begin
268 | state_begin = 0
269 | return time
270 |
271 |
272 | def begin_time(self):
273 | return self.states[0][S_TIME]
274 |
275 | def end_time(self):
276 | return self.states[-1][S_TIME]
277 |
278 | # Enter point
279 | if len(sys.argv) < 2:
280 | print usage.replace("%s", sys.argv[0])
281 | sys.exit(0)
282 |
283 | # parse arguments
284 | include = []
285 | exclude = []
286 | unit_ms = False
287 | graphic = False
288 | ex_mark = False
289 |
290 | try:
291 | for arg in sys.argv[2:]:
292 | if arg == '-m':
293 | unit_ms = True
294 | continue
295 | if arg == '-g':
296 | graphic = True
297 | continue
298 | if not ex_mark:
299 | if arg == '-x':
300 | ex_mark = True
301 | else:
302 | include.append(int(arg))
303 | else:
304 | exclude.append(int(arg))
305 | except ValueError:
306 | print "Bad argument '%s'" % arg
307 | sys.exit(-1)
308 |
309 | # parse log file and construct processes
310 | processes = process_pool()
311 |
312 | f = open(sys.argv[1], "r")
313 |
314 | # Patch process 0's New & Run state
315 | processes.new(0, 40).change_state(P_RUNNING, 40)
316 |
317 | try:
318 | prev_time = 0
319 | prev_line = ""
320 | for lineno, line in enumerate(f):
321 |
322 | if line == prev_line:
323 | raise SameLine
324 | prev_line = line
325 |
326 | fields = line.split("\t")
327 | if len(fields) != 3:
328 | raise BadFormat
329 |
330 | pid = int(fields[0])
331 | s = fields[1].upper()
332 |
333 | time = int(fields[2])
334 | if time < prev_time:
335 | raise BadTime(time)
336 | prev_time = time
337 |
338 | p = processes.get_process(pid)
339 |
340 | state = P_NULL
341 | if s == 'N':
342 | processes.new(pid, time)
343 | elif s == 'J':
344 | state = P_READY
345 | elif s == 'R':
346 | state = P_RUNNING
347 | elif s == 'W':
348 | state = P_WAITING
349 | elif s == 'E':
350 | state = P_EXIT
351 | else:
352 | raise UnknownState(s)
353 | if state != P_NULL:
354 | if not p:
355 | raise NoNew(pid, s)
356 | p.change_state(state, time)
357 | except MyError, err:
358 | print "Error at line %d: %s" % (lineno+1, err)
359 | sys.exit(0)
360 |
361 | # Stats
362 | stats = statistics(processes, include, exclude)
363 | att = stats.average_turnaround()
364 | awt = stats.average_waiting()
365 | if unit_ms:
366 | unit = "ms"
367 | att *= 1000/HZ
368 | awt *= 1000/HZ
369 | else:
370 | unit = "tick"
371 | print "(Unit: %s)" % unit
372 | print "Process Turnaround Waiting CPU Burst I/O Burst"
373 | for pid in stats.list_pid():
374 | p = processes.get_process(pid)
375 | tt = p.turnaround_time()
376 | wt = p.waiting_time()
377 | cpu = p.cpu_time()
378 | io = p.io_time()
379 |
380 | if unit_ms:
381 | print "%7d %10d %7d %9d %9d" % (pid, tt*1000/HZ, wt*1000/HZ, cpu*1000/HZ, io*1000/HZ)
382 | else:
383 | print "%7d %10d %7d %9d %9d" % (pid, tt, wt, cpu, io)
384 | print "Average: %10.2f %7.2f" % (att, awt)
385 | print "Throughout: %.2f/s" % (stats.throughput())
386 |
387 | if graphic:
388 | stats.print_graphic()
389 |
--------------------------------------------------------------------------------
/lab3/sched.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/kernel/sched.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * 'sched.c' is the main kernel file. It contains scheduling primitives
9 | * (sleep_on, wakeup, schedule etc) as well as a number of simple system
10 | * call functions (type getpid(), which just extracts a field from
11 | * current-task
12 | */
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 |
23 | #define _S(nr) (1<<((nr)-1))
24 | #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
25 |
26 | void show_task(int nr,struct task_struct * p)
27 | {
28 | int i,j = 4096-sizeof(struct task_struct);
29 |
30 | printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
31 | i=0;
32 | while (i>2 ] ;
68 |
69 | struct {
70 | long * a;
71 | short b;
72 | } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
73 | /*
74 | * 'math_state_restore()' saves the current math information in the
75 | * old math state array, and gets the new ones from the current task
76 | */
77 | void math_state_restore()
78 | {
79 | if (last_task_used_math == current)
80 | return;
81 | __asm__("fwait");
82 | if (last_task_used_math) {
83 | __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
84 | }
85 | last_task_used_math=current;
86 | if (current->used_math) {
87 | __asm__("frstor %0"::"m" (current->tss.i387));
88 | } else {
89 | __asm__("fninit"::);
90 | current->used_math=1;
91 | }
92 | }
93 |
94 | /*
95 | * 'schedule()' is the scheduler function. This is GOOD CODE! There
96 | * probably won't be any reason to change this, as it should work well
97 | * in all circumstances (ie gives IO-bound processes good response etc).
98 | * The one thing you might take a look at is the signal-handler code here.
99 | *
100 | * NOTE!! Task 0 is the 'idle' task, which gets called when no other
101 | * tasks can run. It can not be killed, and it cannot sleep. The 'state'
102 | * information in task[0] is never used.
103 | */
104 | void schedule(void)
105 | {
106 | int i,next,c;
107 | struct task_struct ** p;
108 |
109 | /* check alarm, wake up any interruptible tasks that have got a signal */
110 |
111 | for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
112 | if (*p) {
113 | if ((*p)->alarm && (*p)->alarm < jiffies) {
114 | (*p)->signal |= (1<<(SIGALRM-1));
115 | (*p)->alarm = 0;
116 | }
117 | if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
118 | (*p)->state==TASK_INTERRUPTIBLE)
119 | {
120 | (*p)->state=TASK_RUNNING;/*唤醒*/
121 | /*可中断睡眠唤醒到就蓄状态*/
122 | /*睡眠->就绪*/
123 | fprintk(3, "%d\tJ\t%d\n", (*p)->pid, jiffies);
124 | }
125 |
126 | }
127 |
128 | /* this is the scheduler proper:修改时间片 */
129 |
130 | while (1) {
131 | c = -1;
132 | next = 0;
133 | i = NR_TASKS;
134 | p = &task[NR_TASKS];
135 | while (--i) {
136 | if (!*--p)
137 | continue;
138 | if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
139 | c = (*p)->counter, next = i;
140 | } /*找到counter值最大的就绪进程*/
141 | if (c) break;/*如果有counter值大于0的就绪态进程,则退出*/
142 | for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
143 | if (*p)
144 | (*p)->counter = ((*p)->counter >> 1) +
145 | (*p)->priority;
146 | /*如果没有,所有进程的counter值除以2衰减后再和priority值相加,产生新的时间片---对所有的进程,包括阻塞态的进程,都进行衰减*/
147 | /*这样,对于正在阻塞的进程来说,一个进程在阻塞队列中停留的时间越长,其优先级约高,被分配的时间片也就会越大*/
148 | /*这种进程调度是一种综合考虑进程优先级并且能动态反馈调整时间片的轮转调度算法*/
149 |
150 | }
151 |
152 | if(current->pid!=task[next]->pid)
153 | {
154 | if(current->state == TASK_RUNNING) /*时间片到,转为就绪状态*/
155 | {
156 | /*运行——>就绪*/
157 | fprintk(3, "%d\tJ\t%d\n", current->pid, jiffies);
158 | }
159 | /*就绪->运行*/
160 | fprintk(3, "%d\tR\t%d\n", task[next]->pid, jiffies);
161 | }
162 | switch_to(next);/*切换到next进程*/
163 | }
164 |
165 | int sys_pause(void)
166 | {
167 | current->state = TASK_INTERRUPTIBLE;
168 | /*运行->可中断睡眠*/
169 | if(current->pid != 0)
170 | {
171 | fprintk(3,"%d\tW\t%d\n",current->pid,jiffies);
172 | }
173 | schedule();
174 | return 0;
175 | }
176 |
177 | void sleep_on(struct task_struct **p)
178 | {
179 | struct task_struct *tmp;
180 |
181 | if (!p)
182 | return;
183 | if (current == &(init_task.task))
184 | panic("task[0] trying to sleep");
185 | tmp = *p;
186 | *p = current; /*将current插入等待队列的头部*/
187 | current->state = TASK_UNINTERRUPTIBLE; /*切换状态到不可中断睡眠状态*/
188 | /*运行->不可中断睡眠*/
189 | fprintk(3,"%d\tW\t%d\n",current->pid,jiffies);
190 | schedule(); /*睡眠状态让出CPU*/
191 | if (tmp)
192 | {
193 | tmp->state=0; /*唤醒队列中的上一个睡眠进程。这儿的0可以换为TASK_RUNNING*/
194 | /*原等待队列中。第一个进程->唤醒就绪*/
195 | fprintk(3,"%d\tJ\t%d\n",tmp->pid,jiffies);
196 | }
197 |
198 | }
199 | /* TASK_UNINTERRUPTIBLE和TASK_INTERRUPTIBLE的区别在于不可中断的睡眠
200 | * 只能由wake_up()显式唤醒,再由上面的 schedule()语句后的
201 | *
202 | * if (tmp) tmp->state=0;
203 | *
204 | * 依次唤醒,所以不可中断的睡眠进程一定是按严格从“队列”(一个依靠
205 | * 放在进程内核栈中的指针变量tmp维护的队列)的首部进行唤醒。而对于可
206 | * 中断的进程,除了用wake_up唤醒以外,也可以用信号(给进程发送一个信
207 | * 号,实际上就是将进程PCB中维护的一个向量的某一位置位,进程需要在合
208 | * 适的时候处理这一位。感兴趣的实验者可以阅读有关代码)来唤醒,如在
209 | * schedule()中:
210 | *
211 | * for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
212 | * if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
213 | * (*p)->state==TASK_INTERRUPTIBLE)
214 | * (*p)->state=TASK_RUNNING;//唤醒
215 | *
216 | * 就是当进程是可中断睡眠时,如果遇到一些信号就将其唤醒。这样的唤醒会
217 | * 出现一个问题,那就是可能会唤醒等待队列中间的某个进程,此时这个链就
218 | * 需要进行适当调整。interruptible_sleep_on和sleep_on函数的主要区别就
219 | * 在这里。
220 | */
221 | /*可中断睡眠,遇到一些进程后就将他唤醒*/
222 | void interruptible_sleep_on(struct task_struct **p)
223 | {
224 | struct task_struct *tmp;
225 |
226 | if (!p)
227 | return;
228 | if (current == &(init_task.task))
229 | panic("task[0] trying to sleep");
230 | tmp=*p;
231 | *p=current;
232 | repeat: current->state = TASK_INTERRUPTIBLE; /*切换到可中断睡眠状态*/
233 | /*唤醒队列的中间成功,通过goto去实现了唤醒 队列中的头进程,进行等待*/
234 | fprintk(3,"%d\tW\t%d\n",current->pid,jiffies);
235 | schedule();
236 | if (*p && *p != current) { /*如果队列头指针的进程和刚唤醒的不是不是同一个进程,说明在队列的中间唤醒来一个进程,需要处理一下*/
237 | (**p).state=0; /*将队列头唤醒,然后通过goto让自己睡眠*/
238 | /*当前进程进行 可中断睡眠*/
239 | fprintk(3,"%d\tJ\t%d\n",(*p)->pid,jiffies);
240 | goto repeat;
241 | }
242 | *p=NULL;
243 | if (tmp)
244 | {
245 | /*原等待队列 第一个进程 唤醒到就绪状态*/
246 | fprintk(3,"%d\tJ\t%d\n",tmp->pid,jiffies);
247 | tmp->state=0;
248 | }
249 |
250 | }
251 |
252 | void wake_up(struct task_struct **p)
253 | {
254 | if (p && *p) {
255 | (**p).state=0;
256 | /*唤醒到就绪状态*/
257 | fprintk(3,"%d\tJ\t%d\n",(*p)->pid,jiffies);
258 | *p=NULL;
259 | }
260 | }
261 |
262 | /*
263 | * OK, here are some floppy things that shouldn't be in the kernel
264 | * proper. They are here because the floppy needs a timer, and this
265 | * was the easiest way of doing it.
266 | */
267 | static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
268 | static int mon_timer[4]={0,0,0,0};
269 | static int moff_timer[4]={0,0,0,0};
270 | unsigned char current_DOR = 0x0C;
271 |
272 | int ticks_to_floppy_on(unsigned int nr)
273 | {
274 | extern unsigned char selected;
275 | unsigned char mask = 0x10 << nr;
276 |
277 | if (nr>3)
278 | panic("floppy_on: nr>3");
279 | moff_timer[nr]=10000; /* 100 s = very big :-) */
280 | cli(); /* use floppy_off to turn it off */
281 | mask |= current_DOR;
282 | if (!selected) {
283 | mask &= 0xFC;
284 | mask |= nr;
285 | }
286 | if (mask != current_DOR) {
287 | outb(mask,FD_DOR);
288 | if ((mask ^ current_DOR) & 0xf0)
289 | mon_timer[nr] = HZ/2;
290 | else if (mon_timer[nr] < 2)
291 | mon_timer[nr] = 2;
292 | current_DOR = mask;
293 | }
294 | sti();
295 | return mon_timer[nr];
296 | }
297 |
298 | void floppy_on(unsigned int nr)
299 | {
300 | cli();
301 | while (ticks_to_floppy_on(nr))
302 | sleep_on(nr+wait_motor);
303 | sti();
304 | }
305 |
306 | void floppy_off(unsigned int nr)
307 | {
308 | moff_timer[nr]=3*HZ;
309 | }
310 |
311 | void do_floppy_timer(void)
312 | {
313 | int i;
314 | unsigned char mask = 0x10;
315 |
316 | for (i=0 ; i<4 ; i++,mask <<= 1) {
317 | if (!(mask & current_DOR))
318 | continue;
319 | if (mon_timer[i]) {
320 | if (!--mon_timer[i])
321 | wake_up(i+wait_motor);
322 | } else if (!moff_timer[i]) {
323 | current_DOR &= ~mask;
324 | outb(current_DOR,FD_DOR);
325 | } else
326 | moff_timer[i]--;
327 | }
328 | }
329 |
330 | #define TIME_REQUESTS 64
331 |
332 | static struct timer_list {
333 | long jiffies;
334 | void (*fn)();
335 | struct timer_list * next;
336 | } timer_list[TIME_REQUESTS], * next_timer = NULL;
337 |
338 | void add_timer(long jiffies, void (*fn)(void))
339 | {
340 | struct timer_list * p;
341 |
342 | if (!fn)
343 | return;
344 | cli();
345 | if (jiffies <= 0)
346 | (fn)();
347 | else {
348 | for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
349 | if (!p->fn)
350 | break;
351 | if (p >= timer_list + TIME_REQUESTS)
352 | panic("No more time requests free");
353 | p->fn = fn;
354 | p->jiffies = jiffies;
355 | p->next = next_timer;
356 | next_timer = p;
357 | while (p->next && p->next->jiffies < p->jiffies) {
358 | p->jiffies -= p->next->jiffies;
359 | fn = p->fn;
360 | p->fn = p->next->fn;
361 | p->next->fn = fn;
362 | jiffies = p->jiffies;
363 | p->jiffies = p->next->jiffies;
364 | p->next->jiffies = jiffies;
365 | p = p->next;
366 | }
367 | }
368 | sti();
369 | }
370 |
371 | void do_timer(long cpl)
372 | {
373 | extern int beepcount;
374 | extern void sysbeepstop(void);
375 |
376 | if (beepcount)
377 | if (!--beepcount)
378 | sysbeepstop();
379 |
380 | if (cpl)
381 | current->utime++;
382 | else
383 | current->stime++;
384 |
385 | if (next_timer) {
386 | next_timer->jiffies--;
387 | while (next_timer && next_timer->jiffies <= 0) {
388 | void (*fn)(void);
389 |
390 | fn = next_timer->fn;
391 | next_timer->fn = NULL;
392 | next_timer = next_timer->next;
393 | (fn)();
394 | }
395 | }
396 | if (current_DOR & 0xf0)
397 | do_floppy_timer();
398 | if ((--current->counter)>0) return;
399 | current->counter=0;
400 | if (!cpl) return;
401 | schedule();
402 | }
403 |
404 | int sys_alarm(long seconds)
405 | {
406 | int old = current->alarm;
407 |
408 | if (old)
409 | old = (old - jiffies) / HZ;
410 | current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
411 | return (old);
412 | }
413 |
414 | int sys_getpid(void)
415 | {
416 | return current->pid;
417 | }
418 |
419 | int sys_getppid(void)
420 | {
421 | return current->father;
422 | }
423 |
424 | int sys_getuid(void)
425 | {
426 | return current->uid;
427 | }
428 |
429 | int sys_geteuid(void)
430 | {
431 | return current->euid;
432 | }
433 |
434 | int sys_getgid(void)
435 | {
436 | return current->gid;
437 | }
438 |
439 | int sys_getegid(void)
440 | {
441 | return current->egid;
442 | }
443 |
444 | int sys_nice(long increment)
445 | {
446 | /*只有在这个系统级函数里面修改过priority */
447 | if (current->priority-increment>0)
448 | current->priority -= increment;
449 | return 0;
450 | }
451 |
452 | void sched_init(void)
453 | {
454 | int i;
455 | struct desc_struct * p;
456 |
457 | if (sizeof(struct sigaction) != 16)
458 | panic("Struct sigaction MUST be 16 bytes");
459 | set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
460 | set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
461 | p = gdt+2+FIRST_TSS_ENTRY;
462 | for(i=1;ia=p->b=0;
465 | p++;
466 | p->a=p->b=0;
467 | p++;
468 | }
469 | /* Clear NT, so that we won't have troubles with that later on */
470 | __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
471 | ltr(0);
472 | lldt(0);
473 | outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
474 | outb_p(LATCH & 0xff , 0x40); /* LSB */
475 | outb(LATCH >> 8 , 0x40); /* MSB */
476 | set_intr_gate(0x20,&timer_interrupt); /*时钟中断处理函数*/
477 | outb(inb_p(0x21)&~0x01,0x21);
478 | set_system_gate(0x80,&system_call);
479 | }
480 |
--------------------------------------------------------------------------------
/lab6/memory.c:
--------------------------------------------------------------------------------
1 | /*
2 | * linux/mm/memory.c
3 | *
4 | * (C) 1991 Linus Torvalds
5 | */
6 |
7 | /*
8 | * demand-loading started 01.12.91 - seems it is high on the list of
9 | * things wanted, and it should be easy to implement. - Linus
10 | */
11 |
12 | /*
13 | * Ok, demand-loading was easy, shared pages a little bit tricker. Shared
14 | * pages started 02.12.91, seems to work. - Linus.
15 | *
16 | * Tested sharing by executing about 30 /bin/sh: under the old kernel it
17 | * would have taken more than the 6M I have free, but it worked well as
18 | * far as I could see.
19 | *
20 | * Also corrected some "invalidate()"s - I wasn't doing enough of them.
21 | */
22 |
23 | #include
24 |
25 | #include
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | volatile void do_exit(long code);
32 |
33 | static inline volatile void oom(void)
34 | {
35 | printk("out of memory\n\r");
36 | do_exit(SIGSEGV);
37 | }
38 |
39 | #define invalidate() \
40 | __asm__("movl %%eax,%%cr3"::"a" (0))
41 |
42 | /* these are not to be changed without changing head.s etc */
43 | #define LOW_MEM 0x100000
44 | #define PAGING_MEMORY (15*1024*1024)
45 | #define PAGING_PAGES (PAGING_MEMORY>>12)
46 | #define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
47 | #define USED 100
48 |
49 | #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
50 | current->start_code + current->end_code)
51 |
52 | static long HIGH_MEMORY = 0;
53 |
54 | #define copy_page(from,to) \
55 | __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024))
56 |
57 | static unsigned char mem_map [ PAGING_PAGES ] = {0,};
58 |
59 | /*
60 | * Get physical address of first (actually last :-) free page, and mark it
61 | * used. If no free pages left, return 0.
62 | */
63 | unsigned long get_free_page(void)
64 | {
65 | register unsigned long __res asm("ax");
66 |
67 | __asm__("std ; repne ; scasb\n\t"
68 | "jne 1f\n\t"
69 | "movb $1,1(%%edi)\n\t"
70 | "sall $12,%%ecx\n\t"
71 | "addl %2,%%ecx\n\t"
72 | "movl %%ecx,%%edx\n\t"
73 | "movl $1024,%%ecx\n\t"
74 | "leal 4092(%%edx),%%edi\n\t"
75 | "rep ; stosl\n\t"
76 | "movl %%edx,%%eax\n"
77 | "1:"
78 | :"=a" (__res)
79 | :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
80 | "D" (mem_map+PAGING_PAGES-1)
81 | );
82 | return __res;
83 | }
84 |
85 | /*
86 | * Free a page of memory at physical address 'addr'. Used by
87 | * 'free_page_tables()'
88 | */
89 | void free_page(unsigned long addr)
90 | {
91 | if (addr < LOW_MEM) return;
92 | if (addr >= HIGH_MEMORY)
93 | panic("trying to free nonexistent page");
94 | addr -= LOW_MEM;
95 | addr >>= 12;
96 | if (mem_map[addr]--) return;
97 | mem_map[addr]=0;
98 | //panic("trying to free free page");
99 | }
100 |
101 | /*
102 | * This function frees a continuos block of page tables, as needed
103 | * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks.
104 | */
105 | int free_page_tables(unsigned long from,unsigned long size)
106 | {
107 | unsigned long *pg_table;
108 | unsigned long * dir, nr;
109 |
110 | if (from & 0x3fffff)
111 | panic("free_page_tables called with wrong alignment");
112 | if (!from)
113 | panic("Trying to free up swapper memory space");
114 | size = (size + 0x3fffff) >> 22;
115 | dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
116 | for ( ; size-->0 ; dir++) {
117 | if (!(1 & *dir))
118 | continue;
119 | pg_table = (unsigned long *) (0xfffff000 & *dir);
120 | for (nr=0 ; nr<1024 ; nr++) {
121 | if (1 & *pg_table)
122 | free_page(0xfffff000 & *pg_table);
123 | *pg_table = 0;
124 | pg_table++;
125 | }
126 | free_page(0xfffff000 & *dir);
127 | *dir = 0;
128 | }
129 | invalidate();
130 | return 0;
131 | }
132 |
133 | /*
134 | * Well, here is one of the most complicated functions in mm. It
135 | * copies a range of linerar addresses by copying only the pages.
136 | * Let's hope this is bug-free, 'cause this one I don't want to debug :-)
137 | *
138 | * Note! We don't copy just any chunks of memory - addresses have to
139 | * be divisible by 4Mb (one page-directory entry), as this makes the
140 | * function easier. It's used only by fork anyway.
141 | *
142 | * NOTE 2!! When from==0 we are copying kernel space for the first
143 | * fork(). Then we DONT want to copy a full page-directory entry, as
144 | * that would lead to some serious memory waste - we just copy the
145 | * first 160 pages - 640kB. Even that is more than we need, but it
146 | * doesn't take any more memory - we don't copy-on-write in the low
147 | * 1 Mb-range, so the pages can be shared with the kernel. Thus the
148 | * special case for nr=xxxx.
149 | */
150 | int copy_page_tables(unsigned long from,unsigned long to,long size)
151 | {
152 | unsigned long * from_page_table;
153 | unsigned long * to_page_table;
154 | unsigned long this_page;
155 | unsigned long * from_dir, * to_dir;
156 | unsigned long nr;
157 |
158 | if ((from&0x3fffff) || (to&0x3fffff))
159 | panic("copy_page_tables called with wrong alignment");
160 | from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
161 | to_dir = (unsigned long *) ((to>>20) & 0xffc);
162 | size = ((unsigned) (size+0x3fffff)) >> 22;
163 | for( ; size-->0 ; from_dir++,to_dir++) {
164 | if (1 & *to_dir)
165 | panic("copy_page_tables: already exist");
166 | if (!(1 & *from_dir))
167 | continue;
168 | from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
169 | if (!(to_page_table = (unsigned long *) get_free_page()))
170 | return -1; /* Out of memory, see freeing */
171 | *to_dir = ((unsigned long) to_page_table) | 7;
172 | nr = (from==0)?0xA0:1024;
173 | for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
174 | this_page = *from_page_table;
175 | if (!(1 & this_page))
176 | continue;
177 | this_page &= ~2;
178 | *to_page_table = this_page;
179 | if (this_page > LOW_MEM) {
180 | *from_page_table = this_page;
181 | this_page -= LOW_MEM;
182 | this_page >>= 12;
183 | mem_map[this_page]++;
184 | }
185 | }
186 | }
187 | invalidate();
188 | return 0;
189 | }
190 |
191 | /*
192 | * This function puts a page in memory at the wanted address.
193 | * It returns the physical address of the page gotten, 0 if
194 | * out of memory (either when trying to access page-table or
195 | * page.)
196 | */
197 | unsigned long put_page(unsigned long page,unsigned long address)
198 | {
199 | unsigned long tmp, *page_table;
200 |
201 | /* NOTE !!! This uses the fact that _pg_dir=0 */
202 |
203 | if (page < LOW_MEM || page >= HIGH_MEMORY)
204 | printk("Trying to put page %p at %p\n",page,address);
205 | if (mem_map[(page-LOW_MEM)>>12] != 1)
206 | printk("mem_map disagrees with %p at %p\n",page,address);
207 | page_table = (unsigned long *) ((address>>20) & 0xffc);
208 | if ((*page_table)&1)
209 | page_table = (unsigned long *) (0xfffff000 & *page_table);
210 | else {
211 | if (!(tmp=get_free_page()))
212 | return 0;
213 | *page_table = tmp|7;
214 | page_table = (unsigned long *) tmp;
215 | }
216 | page_table[(address>>12) & 0x3ff] = page | 7;
217 | /* no need for invalidate */
218 | return page;
219 | }
220 |
221 | void un_wp_page(unsigned long * table_entry)
222 | {
223 | unsigned long old_page,new_page;
224 |
225 | old_page = 0xfffff000 & *table_entry;
226 | if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
227 | *table_entry |= 2;
228 | invalidate();
229 | return;
230 | }
231 | if (!(new_page=get_free_page()))
232 | oom();
233 | if (old_page >= LOW_MEM)
234 | mem_map[MAP_NR(old_page)]--;
235 | *table_entry = new_page | 7;
236 | invalidate();
237 | copy_page(old_page,new_page);
238 | }
239 |
240 | /*
241 | * This routine handles present pages, when users try to write
242 | * to a shared page. It is done by copying the page to a new address
243 | * and decrementing the shared-page counter for the old page.
244 | *
245 | * If it's in code space we exit with a segment error.
246 | */
247 | void do_wp_page(unsigned long error_code,unsigned long address)
248 | {
249 | #if 0
250 | /* we cannot do this yet: the estdio library writes to code space */
251 | /* stupid, stupid. I really want the libc.a from GNU */
252 | if (CODE_SPACE(address))
253 | do_exit(SIGSEGV);
254 | #endif
255 | un_wp_page((unsigned long *)
256 | (((address>>10) & 0xffc) + (0xfffff000 &
257 | *((unsigned long *) ((address>>20) &0xffc)))));
258 |
259 | }
260 |
261 | void write_verify(unsigned long address)
262 | {
263 | unsigned long page;
264 |
265 | if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1))
266 | return;
267 | page &= 0xfffff000;
268 | page += ((address>>10) & 0xffc);
269 | if ((3 & *(unsigned long *) page) == 1) /* non-writeable, present */
270 | un_wp_page((unsigned long *) page);
271 | return;
272 | }
273 |
274 | void get_empty_page(unsigned long address)
275 | {
276 | unsigned long tmp;
277 |
278 | if (!(tmp=get_free_page()) || !put_page(tmp,address)) {
279 | free_page(tmp); /* 0 is ok - ignored */
280 | oom();
281 | }
282 | }
283 |
284 | /*
285 | * try_to_share() checks the page at address "address" in the task "p",
286 | * to see if it exists, and if it is clean. If so, share it with the current
287 | * task.
288 | *
289 | * NOTE! This assumes we have checked that p != current, and that they
290 | * share the same executable.
291 | */
292 | static int try_to_share(unsigned long address, struct task_struct * p)
293 | {
294 | unsigned long from;
295 | unsigned long to;
296 | unsigned long from_page;
297 | unsigned long to_page;
298 | unsigned long phys_addr;
299 |
300 | from_page = to_page = ((address>>20) & 0xffc);
301 | from_page += ((p->start_code>>20) & 0xffc);
302 | to_page += ((current->start_code>>20) & 0xffc);
303 | /* is there a page-directory at from? */
304 | from = *(unsigned long *) from_page;
305 | if (!(from & 1))
306 | return 0;
307 | from &= 0xfffff000;
308 | from_page = from + ((address>>10) & 0xffc);
309 | phys_addr = *(unsigned long *) from_page;
310 | /* is the page clean and present? */
311 | if ((phys_addr & 0x41) != 0x01)
312 | return 0;
313 | phys_addr &= 0xfffff000;
314 | if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM)
315 | return 0;
316 | to = *(unsigned long *) to_page;
317 | if (!(to & 1)) {
318 | if ((to = get_free_page()))
319 | *(unsigned long *) to_page = to | 7;
320 | else
321 | oom();
322 | }
323 | to &= 0xfffff000;
324 | to_page = to + ((address>>10) & 0xffc);
325 | if (1 & *(unsigned long *) to_page)
326 | panic("try_to_share: to_page already exists");
327 | /* share them: write-protect */
328 | *(unsigned long *) from_page &= ~2;
329 | *(unsigned long *) to_page = *(unsigned long *) from_page;
330 | invalidate();
331 | phys_addr -= LOW_MEM;
332 | phys_addr >>= 12;
333 | mem_map[phys_addr]++;
334 | return 1;
335 | }
336 |
337 | /*
338 | * share_page() tries to find a process that could share a page with
339 | * the current one. Address is the address of the wanted page relative
340 | * to the current data space.
341 | *
342 | * We first check if it is at all feasible by checking executable->i_count.
343 | * It should be >1 if there are other tasks sharing this inode.
344 | */
345 | static int share_page(unsigned long address)
346 | {
347 | struct task_struct ** p;
348 |
349 | if (!current->executable)
350 | return 0;
351 | if (current->executable->i_count < 2)
352 | return 0;
353 | for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
354 | if (!*p)
355 | continue;
356 | if (current == *p)
357 | continue;
358 | if ((*p)->executable != current->executable)
359 | continue;
360 | if (try_to_share(address,*p))
361 | return 1;
362 | }
363 | return 0;
364 | }
365 |
366 | void do_no_page(unsigned long error_code,unsigned long address)
367 | {
368 | int nr[4];
369 | unsigned long tmp;
370 | unsigned long page;
371 | int block,i;
372 |
373 | address &= 0xfffff000;
374 | tmp = address - current->start_code;
375 | if (!current->executable || tmp >= current->end_data) {
376 | get_empty_page(address);
377 | return;
378 | }
379 | if (share_page(tmp))
380 | return;
381 | if (!(page = get_free_page()))
382 | oom();
383 | /* remember that 1 block is used for header */
384 | block = 1 + tmp/BLOCK_SIZE;
385 | for (i=0 ; i<4 ; block++,i++)
386 | nr[i] = bmap(current->executable,block);
387 | bread_page(page,current->executable->i_dev,nr);
388 | i = tmp + 4096 - current->end_data;
389 | tmp = page + 4096;
390 | while (i-- > 0) {
391 | tmp--;
392 | *(char *)tmp = 0;
393 | }
394 | if (put_page(page,address))
395 | return;
396 | free_page(page);
397 | oom();
398 | }
399 |
400 | void mem_init(long start_mem, long end_mem)
401 | {
402 | int i;
403 |
404 | HIGH_MEMORY = end_mem;
405 | for (i=0 ; i>= 12;
410 | while (end_mem-->0)
411 | mem_map[i++]=0;
412 | }
413 |
414 | void calc_mem(void)
415 | {
416 | int i,j,k,free=0;
417 | long * pg_tbl;
418 |
419 | for(i=0 ; i
14 |
15 | .text
16 | .globl keyboard_interrupt
17 |
18 | /*
19 | * these are for the keyboard read functions
20 | */
21 | size = 1024 /* must be a power of two ! And MUST be the same
22 | as in tty_io.c !!!! */
23 | head = 4
24 | tail = 8
25 | proc_list = 12
26 | buf = 16
27 |
28 | mode: .byte 0 /* caps, alt, ctrl and shift mode */
29 | leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
30 | e0: .byte 0
31 |
32 | /*
33 | * con_int is the real interrupt routine that reads the
34 | * keyboard scan-code and converts it into the appropriate
35 | * ascii character(s).
36 | */
37 | keyboard_interrupt:
38 | pushl %eax
39 | pushl %ebx
40 | pushl %ecx
41 | pushl %edx
42 | push %ds
43 | push %es
44 | movl $0x10,%eax
45 | mov %ax,%ds
46 | mov %ax,%es
47 | xor %al,%al /* %eax is scan code */
48 | inb $0x60,%al
49 | cmpb $0xe0,%al
50 | je set_e0
51 | cmpb $0xe1,%al
52 | je set_e1
53 | call key_table(,%eax,4)
54 | movb $0,e0
55 | e0_e1: inb $0x61,%al
56 | jmp 1f
57 | 1: jmp 1f
58 | 1: orb $0x80,%al
59 | jmp 1f
60 | 1: jmp 1f
61 | 1: outb %al,$0x61
62 | jmp 1f
63 | 1: jmp 1f
64 | 1: andb $0x7F,%al
65 | outb %al,$0x61
66 | movb $0x20,%al
67 | outb %al,$0x20
68 | pushl $0
69 | call do_tty_interrupt
70 | addl $4,%esp
71 | pop %es
72 | pop %ds
73 | popl %edx
74 | popl %ecx
75 | popl %ebx
76 | popl %eax
77 | iret
78 | set_e0: movb $1,e0
79 | jmp e0_e1
80 | set_e1: movb $2,e0
81 | jmp e0_e1
82 |
83 | /*
84 | * This routine fills the buffer with max 8 bytes, taken from
85 | * %ebx:%eax. (%edx is high). The bytes are written in the
86 | * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
87 | */
88 | put_queue:
89 | pushl %ecx
90 | pushl %edx
91 | movl table_list,%edx # read-queue for console
92 | movl head(%edx),%ecx
93 | 1: movb %al,buf(%edx,%ecx)
94 | incl %ecx
95 | andl $size-1,%ecx
96 | cmpl tail(%edx),%ecx # buffer full - discard everything
97 | je 3f
98 | shrdl $8,%ebx,%eax
99 | je 2f
100 | shrl $8,%ebx
101 | jmp 1b
102 | 2: movl %ecx,head(%edx)
103 | movl proc_list(%edx),%ecx
104 | testl %ecx,%ecx
105 | je 3f
106 | movl $0,(%ecx)
107 | 3: popl %edx
108 | popl %ecx
109 | ret
110 |
111 | ctrl: movb $0x04,%al
112 | jmp 1f
113 | alt: movb $0x10,%al
114 | 1: cmpb $0,e0
115 | je 2f
116 | addb %al,%al
117 | 2: orb %al,mode
118 | ret
119 | unctrl: movb $0x04,%al
120 | jmp 1f
121 | unalt: movb $0x10,%al
122 | 1: cmpb $0,e0
123 | je 2f
124 | addb %al,%al
125 | 2: notb %al
126 | andb %al,mode
127 | ret
128 |
129 | lshift:
130 | orb $0x01,mode
131 | ret
132 | unlshift:
133 | andb $0xfe,mode
134 | ret
135 | rshift:
136 | orb $0x02,mode
137 | ret
138 | unrshift:
139 | andb $0xfd,mode
140 | ret
141 |
142 | caps: testb $0x80,mode
143 | jne 1f
144 | xorb $4,leds
145 | xorb $0x40,mode
146 | orb $0x80,mode
147 | set_leds:
148 | call kb_wait
149 | movb $0xed,%al /* set leds command */
150 | outb %al,$0x60
151 | call kb_wait
152 | movb leds,%al
153 | outb %al,$0x60
154 | ret
155 | uncaps: andb $0x7f,mode
156 | ret
157 | scroll:
158 | xorb $1,leds
159 | jmp set_leds
160 | num: xorb $2,leds
161 | jmp set_leds
162 |
163 | /*
164 | * curosr-key/numeric keypad cursor keys are handled here.
165 | * checking for numeric keypad etc.
166 | */
167 | cursor:
168 | subb $0x47,%al
169 | jb 1f
170 | cmpb $12,%al
171 | ja 1f
172 | jne cur2 /* check for ctrl-alt-del */
173 | testb $0x0c,mode
174 | je cur2
175 | testb $0x30,mode
176 | jne reboot
177 | cur2: cmpb $0x01,e0 /* e0 forces cursor movement */
178 | je cur
179 | testb $0x02,leds /* not num-lock forces cursor */
180 | je cur
181 | testb $0x03,mode /* shift forces cursor */
182 | jne cur
183 | xorl %ebx,%ebx
184 | movb num_table(%eax),%al
185 | jmp put_queue
186 | 1: ret
187 |
188 | cur: movb cur_table(%eax),%al
189 | cmpb $'9,%al
190 | ja ok_cur
191 | movb $'~,%ah
192 | ok_cur: shll $16,%eax
193 | movw $0x5b1b,%ax
194 | xorl %ebx,%ebx
195 | jmp put_queue
196 |
197 | #if defined(KBD_FR)
198 | num_table:
199 | .ascii "789 456 1230."
200 | #else
201 | num_table:
202 | .ascii "789 456 1230,"
203 | #endif
204 | cur_table:
205 | .ascii "HA5 DGC YB623"
206 |
207 | /*
208 | * this routine handles function keys
209 | */
210 | func:
211 | pushl %eax
212 | pushl %ecx
213 | pushl %edx
214 | /* call show_stat */
215 | popl %edx
216 | popl %ecx
217 | popl %eax
218 | subb $0x3B,%al
219 | jb end_func
220 | cmpb $9,%al
221 | jbe ok_func
222 | subb $18,%al
223 | cmpb $10,%al
224 | jb end_func
225 | cmpb $11,%al
226 | ja end_func
227 | ok_func:
228 | cmpl $4,%ecx /* check that there is enough room */
229 | jl end_func
230 | movl func_table(,%eax,4),%eax
231 | xorl %ebx,%ebx
232 | jmp put_queue
233 | end_func:
234 | ret
235 |
236 | /*
237 | * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
238 | */
239 | func_table:
240 | .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
241 | .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
242 | .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
243 |
244 | #if defined(KBD_FINNISH)
245 | key_map:
246 | .byte 0,27
247 | .ascii "1234567890+'"
248 | .byte 127,9
249 | .ascii "qwertyuiop}"
250 | .byte 0,13,0
251 | .ascii "asdfghjkl|{"
252 | .byte 0,0
253 | .ascii "'zxcvbnm,.-"
254 | .byte 0,'*,0,32 /* 36-39 */
255 | .fill 16,1,0 /* 3A-49 */
256 | .byte '-,0,0,0,'+ /* 4A-4E */
257 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
258 | .byte '<
259 | .fill 10,1,0
260 |
261 | shift_map:
262 | .byte 0,27
263 | .ascii "!\"#$%&/()=?`"
264 | .byte 127,9
265 | .ascii "QWERTYUIOP]^"
266 | .byte 13,0
267 | .ascii "ASDFGHJKL\\["
268 | .byte 0,0
269 | .ascii "*ZXCVBNM;:_"
270 | .byte 0,'*,0,32 /* 36-39 */
271 | .fill 16,1,0 /* 3A-49 */
272 | .byte '-,0,0,0,'+ /* 4A-4E */
273 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
274 | .byte '>
275 | .fill 10,1,0
276 |
277 | alt_map:
278 | .byte 0,0
279 | .ascii "\0@\0$\0\0{[]}\\\0"
280 | .byte 0,0
281 | .byte 0,0,0,0,0,0,0,0,0,0,0
282 | .byte '~,13,0
283 | .byte 0,0,0,0,0,0,0,0,0,0,0
284 | .byte 0,0
285 | .byte 0,0,0,0,0,0,0,0,0,0,0
286 | .byte 0,0,0,0 /* 36-39 */
287 | .fill 16,1,0 /* 3A-49 */
288 | .byte 0,0,0,0,0 /* 4A-4E */
289 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
290 | .byte '|
291 | .fill 10,1,0
292 |
293 | #elif defined(KBD_US)
294 |
295 | key_map:
296 | .byte 0,27
297 | .ascii "1234567890-="
298 | .byte 127,9
299 | .ascii "qwertyuiop[]"
300 | .byte 13,0
301 | .ascii "asdfghjkl;'"
302 | .byte '`,0
303 | .ascii "\\zxcvbnm,./"
304 | .byte 0,'*,0,32 /* 36-39 */
305 | .fill 16,1,0 /* 3A-49 */
306 | .byte '-,0,0,0,'+ /* 4A-4E */
307 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
308 | .byte '<
309 | .fill 10,1,0
310 |
311 |
312 | shift_map:
313 | .byte 0,27
314 | .ascii "!@#$%^&*()_+"
315 | .byte 127,9
316 | .ascii "QWERTYUIOP{}"
317 | .byte 13,0
318 | .ascii "ASDFGHJKL:\""
319 | .byte '~,0
320 | .ascii "|ZXCVBNM<>?"
321 | .byte 0,'*,0,32 /* 36-39 */
322 | .fill 16,1,0 /* 3A-49 */
323 | .byte '-,0,0,0,'+ /* 4A-4E */
324 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
325 | .byte '>
326 | .fill 10,1,0
327 |
328 | alt_map:
329 | .byte 0,0
330 | .ascii "\0@\0$\0\0{[]}\\\0"
331 | .byte 0,0
332 | .byte 0,0,0,0,0,0,0,0,0,0,0
333 | .byte '~,13,0
334 | .byte 0,0,0,0,0,0,0,0,0,0,0
335 | .byte 0,0
336 | .byte 0,0,0,0,0,0,0,0,0,0,0
337 | .byte 0,0,0,0 /* 36-39 */
338 | .fill 16,1,0 /* 3A-49 */
339 | .byte 0,0,0,0,0 /* 4A-4E */
340 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
341 | .byte '|
342 | .fill 10,1,0
343 |
344 | #elif defined(KBD_GR)
345 |
346 | key_map:
347 | .byte 0,27
348 | .ascii "1234567890\\'"
349 | .byte 127,9
350 | .ascii "qwertzuiop@+"
351 | .byte 13,0
352 | .ascii "asdfghjkl[]^"
353 | .byte 0,'#
354 | .ascii "yxcvbnm,.-"
355 | .byte 0,'*,0,32 /* 36-39 */
356 | .fill 16,1,0 /* 3A-49 */
357 | .byte '-,0,0,0,'+ /* 4A-4E */
358 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
359 | .byte '<
360 | .fill 10,1,0
361 |
362 |
363 | shift_map:
364 | .byte 0,27
365 | .ascii "!\"#$%&/()=?`"
366 | .byte 127,9
367 | .ascii "QWERTZUIOP\\*"
368 | .byte 13,0
369 | .ascii "ASDFGHJKL{}~"
370 | .byte 0,''
371 | .ascii "YXCVBNM;:_"
372 | .byte 0,'*,0,32 /* 36-39 */
373 | .fill 16,1,0 /* 3A-49 */
374 | .byte '-,0,0,0,'+ /* 4A-4E */
375 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
376 | .byte '>
377 | .fill 10,1,0
378 |
379 | alt_map:
380 | .byte 0,0
381 | .ascii "\0@\0$\0\0{[]}\\\0"
382 | .byte 0,0
383 | .byte '@,0,0,0,0,0,0,0,0,0,0
384 | .byte '~,13,0
385 | .byte 0,0,0,0,0,0,0,0,0,0,0
386 | .byte 0,0
387 | .byte 0,0,0,0,0,0,0,0,0,0,0
388 | .byte 0,0,0,0 /* 36-39 */
389 | .fill 16,1,0 /* 3A-49 */
390 | .byte 0,0,0,0,0 /* 4A-4E */
391 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
392 | .byte '|
393 | .fill 10,1,0
394 |
395 |
396 | #elif defined(KBD_FR)
397 |
398 | key_map:
399 | .byte 0,27
400 | .ascii "&{\"'(-}_/@)="
401 | .byte 127,9
402 | .ascii "azertyuiop^$"
403 | .byte 13,0
404 | .ascii "qsdfghjklm|"
405 | .byte '`,0,42 /* coin sup gauche, don't know, [*|mu] */
406 | .ascii "wxcvbn,;:!"
407 | .byte 0,'*,0,32 /* 36-39 */
408 | .fill 16,1,0 /* 3A-49 */
409 | .byte '-,0,0,0,'+ /* 4A-4E */
410 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
411 | .byte '<
412 | .fill 10,1,0
413 |
414 | shift_map:
415 | .byte 0,27
416 | .ascii "1234567890]+"
417 | .byte 127,9
418 | .ascii "AZERTYUIOP<>"
419 | .byte 13,0
420 | .ascii "QSDFGHJKLM%"
421 | .byte '~,0,'#
422 | .ascii "WXCVBN?./\\"
423 | .byte 0,'*,0,32 /* 36-39 */
424 | .fill 16,1,0 /* 3A-49 */
425 | .byte '-,0,0,0,'+ /* 4A-4E */
426 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
427 | .byte '>
428 | .fill 10,1,0
429 |
430 | alt_map:
431 | .byte 0,0
432 | .ascii "\0~#{[|`\\^@]}"
433 | .byte 0,0
434 | .byte '@,0,0,0,0,0,0,0,0,0,0
435 | .byte '~,13,0
436 | .byte 0,0,0,0,0,0,0,0,0,0,0
437 | .byte 0,0
438 | .byte 0,0,0,0,0,0,0,0,0,0,0
439 | .byte 0,0,0,0 /* 36-39 */
440 | .fill 16,1,0 /* 3A-49 */
441 | .byte 0,0,0,0,0 /* 4A-4E */
442 | .byte 0,0,0,0,0,0,0 /* 4F-55 */
443 | .byte '|
444 | .fill 10,1,0
445 |
446 | #else
447 | #error "KBD-type not defined"
448 | #endif
449 | /*
450 | * do_self handles "normal" keys, ie keys that don't change meaning
451 | * and which have just one character returns.
452 | */
453 | do_self:
454 | lea alt_map,%ebx
455 | testb $0x20,mode /* alt-gr */
456 | jne 1f
457 | lea shift_map,%ebx
458 | testb $0x03,mode
459 | jne 1f
460 | lea key_map,%ebx
461 | 1: movb (%ebx,%eax),%al
462 | orb %al,%al
463 | je none
464 | testb $0x4c,mode /* ctrl or caps */
465 | je 2f
466 | cmpb $'a,%al
467 | jb 2f
468 | cmpb $'},%al
469 | ja 2f
470 | subb $32,%al
471 | 2: testb $0x0c,mode /* ctrl */
472 | je 3f
473 | cmpb $64,%al
474 | jb 3f
475 | cmpb $64+32,%al
476 | jae 3f
477 | subb $64,%al
478 | 3: testb $0x10,mode /* left alt */
479 | je 4f
480 | orb $0x80,%al
481 | 4: andl $0xff,%eax
482 | xorl %ebx,%ebx
483 | call put_queue
484 | none: ret
485 |
486 | /*
487 | * minus has a routine of it's own, as a 'E0h' before
488 | * the scan code for minus means that the numeric keypad
489 | * slash was pushed.
490 | */
491 | minus: cmpb $1,e0
492 | jne do_self
493 | movl $'/,%eax
494 | xorl %ebx,%ebx
495 | jmp put_queue
496 |
497 | /*
498 | * This table decides which routine to call when a scan-code has been
499 | * gotten. Most routines just call do_self, or none, depending if
500 | * they are make or break.
501 | */
502 | key_table:
503 | .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
504 | .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
505 | .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */
506 | .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */
507 | .long do_self,do_self,do_self,do_self /* 10-13 q w e r */
508 | .long do_self,do_self,do_self,do_self /* 14-17 t y u i */
509 | .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */
510 | .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */
511 | .long do_self,do_self,do_self,do_self /* 20-23 d f g h */
512 | .long do_self,do_self,do_self,do_self /* 24-27 j k l | */
513 | .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */
514 | .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */
515 | .long do_self,do_self,do_self,do_self /* 30-33 b n m , */
516 | .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */
517 | .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */
518 | .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */
519 | .long func,func,func,func /* 40-43 f6 f7 f8 f9 */
520 | .long func,num,scroll,cursor /* 44-47 f10 num scr home */
521 | .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */
522 | .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */
523 | .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */
524 | .long none,none,do_self,func /* 54-57 sysreq ? < f11 */
525 | .long func,none,none,none /* 58-5B f12 ? ? ? */
526 | .long none,none,none,none /* 5C-5F ? ? ? ? */
527 | .long none,none,none,none /* 60-63 ? ? ? ? */
528 | .long none,none,none,none /* 64-67 ? ? ? ? */
529 | .long none,none,none,none /* 68-6B ? ? ? ? */
530 | .long none,none,none,none /* 6C-6F ? ? ? ? */
531 | .long none,none,none,none /* 70-73 ? ? ? ? */
532 | .long none,none,none,none /* 74-77 ? ? ? ? */
533 | .long none,none,none,none /* 78-7B ? ? ? ? */
534 | .long none,none,none,none /* 7C-7F ? ? ? ? */
535 | .long none,none,none,none /* 80-83 ? br br br */
536 | .long none,none,none,none /* 84-87 br br br br */
537 | .long none,none,none,none /* 88-8B br br br br */
538 | .long none,none,none,none /* 8C-8F br br br br */
539 | .long none,none,none,none /* 90-93 br br br br */
540 | .long none,none,none,none /* 94-97 br br br br */
541 | .long none,none,none,none /* 98-9B br br br br */
542 | .long none,unctrl,none,none /* 9C-9F br unctrl br br */
543 | .long none,none,none,none /* A0-A3 br br br br */
544 | .long none,none,none,none /* A4-A7 br br br br */
545 | .long none,none,unlshift,none /* A8-AB br br unlshift br */
546 | .long none,none,none,none /* AC-AF br br br br */
547 | .long none,none,none,none /* B0-B3 br br br br */
548 | .long none,none,unrshift,none /* B4-B7 br br unrshift br */
549 | .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */
550 | .long none,none,none,none /* BC-BF br br br br */
551 | .long none,none,none,none /* C0-C3 br br br br */
552 | .long none,none,none,none /* C4-C7 br br br br */
553 | .long none,none,none,none /* C8-CB br br br br */
554 | .long none,none,none,none /* CC-CF br br br br */
555 | .long none,none,none,none /* D0-D3 br br br br */
556 | .long none,none,none,none /* D4-D7 br br br br */
557 | .long none,none,none,none /* D8-DB br ? ? ? */
558 | .long none,none,none,none /* DC-DF ? ? ? ? */
559 | .long none,none,none,none /* E0-E3 e0 e1 ? ? */
560 | .long none,none,none,none /* E4-E7 ? ? ? ? */
561 | .long none,none,none,none /* E8-EB ? ? ? ? */
562 | .long none,none,none,none /* EC-EF ? ? ? ? */
563 | .long none,none,none,none /* F0-F3 ? ? ? ? */
564 | .long none,none,none,none /* F4-F7 ? ? ? ? */
565 | .long none,none,none,none /* F8-FB ? ? ? ? */
566 | .long none,none,none,none /* FC-FF ? ? ? ? */
567 |
568 | /*
569 | * kb_wait waits for the keyboard controller buffer to empty.
570 | * there is no timeout - if the buffer doesn't empty, we hang.
571 | */
572 | kb_wait:
573 | pushl %eax
574 | 1: inb $0x64,%al
575 | testb $0x02,%al
576 | jne 1b
577 | popl %eax
578 | ret
579 | /*
580 | * This routine reboots the machine by asking the keyboard
581 | * controller to pulse the reset-line low.
582 | */
583 | reboot:
584 | call kb_wait
585 | movw $0x1234,0x472 /* don't do memory check */
586 | movb $0xfc,%al /* pulse reset and A20 low */
587 | outb %al,$0x64
588 | die: jmp die
589 |
--------------------------------------------------------------------------------