├── .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 | --------------------------------------------------------------------------------