Update 209 files
lyx123 authored
- /linux0.11/bochsout.txt
- /linux0.11/dbg-asm
- /linux0.11/dbg-c
- /linux0.11/gdb-cmd.txt
- /linux0.11/mount-hdc
- /linux0.11/run
- /linux0.11/rungdb
- /linux0.11/swaptest.c
- /linux0.11/gdb
- /linux0.11/newdisk.img
- /linux0.11/hdc-0.11.img
- /linux0.11/bochs/bochs-dbg
- /linux0.11/bochs/bochs-gdb
- /linux0.11/bochs/BIOS-bochs-latest
- /linux0.11/bochs/bochsrc-gdb.bxrc
- /linux0.11/bochs/bochsrc.bxrc
- /linux0.11/bochs/bochsrc.bxrc~
- /linux0.11/bochs/vgabios.bin
- /linux0.11/hdc/umounted
- /linux0.11/linux-0.11/Image
- /linux0.11/linux-0.11/Makefile
- /linux0.11/linux-0.11/System.map
- /linux0.11/linux-0.11/tags
- /linux0.11/linux-0.11/boot/bootsect
- /linux0.11/linux-0.11/boot/bootsect.o
- /linux0.11/linux-0.11/boot/bootsect.s
- /linux0.11/linux-0.11/boot/head.o
- /linux0.11/linux-0.11/boot/head.s
- /linux0.11/linux-0.11/boot/setup
- /linux0.11/linux-0.11/boot/setup.o
- /linux0.11/linux-0.11/boot/setup.s
- /linux0.11/linux-0.11/fs/bitmap.c
- /linux0.11/linux-0.11/fs/bitmap.o
- /linux0.11/linux-0.11/fs/block_dev.c
- /linux0.11/linux-0.11/fs/block_dev.o
- /linux0.11/linux-0.11/fs/buffer.c
- /linux0.11/linux-0.11/fs/buffer.o
- /linux0.11/linux-0.11/fs/char_dev.c
- /linux0.11/linux-0.11/fs/char_dev.o
- /linux0.11/linux-0.11/fs/exec.c
- /linux0.11/linux-0.11/fs/exec.o
- /linux0.11/linux-0.11/fs/fcntl.c
- /linux0.11/linux-0.11/fs/fcntl.o
- /linux0.11/linux-0.11/fs/file_dev.c
- /linux0.11/linux-0.11/fs/file_dev.o
- /linux0.11/linux-0.11/fs/file_table.c
- /linux0.11/linux-0.11/fs/file_table.o
- /linux0.11/linux-0.11/fs/fs.o
- /linux0.11/linux-0.11/fs/inode.c
- /linux0.11/linux-0.11/fs/inode.o
- /linux0.11/linux-0.11/fs/ioctl.c
- /linux0.11/linux-0.11/fs/ioctl.o
- /linux0.11/linux-0.11/fs/Makefile
- /linux0.11/linux-0.11/fs/namei.c
- /linux0.11/linux-0.11/fs/namei.o
- /linux0.11/linux-0.11/fs/open.c
- /linux0.11/linux-0.11/fs/open.o
- /linux0.11/linux-0.11/fs/pipe.c
- /linux0.11/linux-0.11/fs/pipe.o
- /linux0.11/linux-0.11/fs/read_write.c
- /linux0.11/linux-0.11/fs/read_write.o
- /linux0.11/linux-0.11/fs/stat.c
- /linux0.11/linux-0.11/fs/stat.o
- /linux0.11/linux-0.11/fs/super.c
- /linux0.11/linux-0.11/fs/super.o
- /linux0.11/linux-0.11/fs/truncate.c
- /linux0.11/linux-0.11/fs/truncate.o
- /linux0.11/linux-0.11/include/a.out.h
- /linux0.11/linux-0.11/include/const.h
- /linux0.11/linux-0.11/include/ctype.h
- /linux0.11/linux-0.11/include/errno.h
- /linux0.11/linux-0.11/include/fcntl.h
- /linux0.11/linux-0.11/include/signal.h
- /linux0.11/linux-0.11/include/stdarg.h
- /linux0.11/linux-0.11/include/stddef.h
- /linux0.11/linux-0.11/include/string.h
- /linux0.11/linux-0.11/include/termios.h
- /linux0.11/linux-0.11/include/time.h
- /linux0.11/linux-0.11/include/unistd.h
- /linux0.11/linux-0.11/include/utime.h
- /linux0.11/linux-0.11/include/asm/io.h
- /linux0.11/linux-0.11/include/asm/memory.h
- /linux0.11/linux-0.11/include/asm/segment.h
- /linux0.11/linux-0.11/include/asm/system.h
- /linux0.11/linux-0.11/include/linux/config.h
- /linux0.11/linux-0.11/include/linux/fdreg.h
- /linux0.11/linux-0.11/include/linux/fs.h
- /linux0.11/linux-0.11/include/linux/hdreg.h
- /linux0.11/linux-0.11/include/linux/head.h
- /linux0.11/linux-0.11/include/linux/kernel.h
- /linux0.11/linux-0.11/include/linux/mm.h
- /linux0.11/linux-0.11/include/linux/sched.h
- /linux0.11/linux-0.11/include/linux/sched.h.cur1
- /linux0.11/linux-0.11/include/linux/sched.h.old
- /linux0.11/linux-0.11/include/linux/sys.h
- /linux0.11/linux-0.11/include/linux/tty.h
- /linux0.11/linux-0.11/include/sys/stat.h
- /linux0.11/linux-0.11/include/sys/times.h
- /linux0.11/linux-0.11/include/sys/types.h
- /linux0.11/linux-0.11/include/sys/utsname.h
- /linux0.11/linux-0.11/include/sys/wait.h
- /linux0.11/linux-0.11/init/main.c
- /linux0.11/linux-0.11/init/main.o
- /linux0.11/linux-0.11/kernel/asm.o
- /linux0.11/linux-0.11/kernel/asm.s
- /linux0.11/linux-0.11/kernel/exit.c
- /linux0.11/linux-0.11/kernel/exit.o
- /linux0.11/linux-0.11/kernel/fork.c
- /linux0.11/linux-0.11/kernel/fork.o
- /linux0.11/linux-0.11/kernel/kernel.o
- /linux0.11/linux-0.11/kernel/Makefile
- /linux0.11/linux-0.11/kernel/mktime.c
- /linux0.11/linux-0.11/kernel/mktime.o
- /linux0.11/linux-0.11/kernel/panic.c
- /linux0.11/linux-0.11/kernel/panic.o
- /linux0.11/linux-0.11/kernel/printk.c
- /linux0.11/linux-0.11/kernel/printk.o
- /linux0.11/linux-0.11/kernel/sched.c
- /linux0.11/linux-0.11/kernel/sched.o
- /linux0.11/linux-0.11/kernel/signal.c
- /linux0.11/linux-0.11/kernel/signal.o
- /linux0.11/linux-0.11/kernel/sys.c
- /linux0.11/linux-0.11/kernel/sys.o
- /linux0.11/linux-0.11/kernel/system_call.o
- /linux0.11/linux-0.11/kernel/system_call.s
- /linux0.11/linux-0.11/kernel/traps.c
- /linux0.11/linux-0.11/kernel/traps.o
- /linux0.11/linux-0.11/kernel/vsprintf.c
- /linux0.11/linux-0.11/kernel/vsprintf.o
- /linux0.11/linux-0.11/kernel/blk_drv/blk.h
- /linux0.11/linux-0.11/kernel/blk_drv/blk_drv.a
- /linux0.11/linux-0.11/kernel/blk_drv/floppy.c
- /linux0.11/linux-0.11/kernel/blk_drv/floppy.o
- /linux0.11/linux-0.11/kernel/blk_drv/hd.c
- /linux0.11/linux-0.11/kernel/blk_drv/hd.o
- /linux0.11/linux-0.11/kernel/blk_drv/ll_rw_blk.c
- /linux0.11/linux-0.11/kernel/blk_drv/ll_rw_blk.o
- /linux0.11/linux-0.11/kernel/blk_drv/Makefile
- /linux0.11/linux-0.11/kernel/blk_drv/ramdisk.c
- /linux0.11/linux-0.11/kernel/blk_drv/ramdisk.o
- /linux0.11/linux-0.11/kernel/chr_drv/chr_drv.a
- /linux0.11/linux-0.11/kernel/chr_drv/console.c
- /linux0.11/linux-0.11/kernel/chr_drv/console.o
- /linux0.11/linux-0.11/kernel/chr_drv/keyboard.o
- /linux0.11/linux-0.11/kernel/chr_drv/keyboard.S
- /linux0.11/linux-0.11/kernel/chr_drv/Makefile
- /linux0.11/linux-0.11/kernel/chr_drv/rs_io.o
- /linux0.11/linux-0.11/kernel/chr_drv/rs_io.s
- /linux0.11/linux-0.11/kernel/chr_drv/serial.c
- /linux0.11/linux-0.11/kernel/chr_drv/serial.o
- /linux0.11/linux-0.11/kernel/chr_drv/tty_io.c
- /linux0.11/linux-0.11/kernel/chr_drv/tty_io.o
- /linux0.11/linux-0.11/kernel/chr_drv/tty_ioctl.c
- /linux0.11/linux-0.11/kernel/chr_drv/tty_ioctl.o
- /linux0.11/linux-0.11/kernel/math/Makefile
- /linux0.11/linux-0.11/kernel/math/math.a
- /linux0.11/linux-0.11/kernel/math/math_emulate.c
- /linux0.11/linux-0.11/kernel/math/math_emulate.o
- /linux0.11/linux-0.11/lib/close.c
- /linux0.11/linux-0.11/lib/close.o
- /linux0.11/linux-0.11/lib/ctype.c
- /linux0.11/linux-0.11/lib/ctype.o
- /linux0.11/linux-0.11/lib/dup.c
- /linux0.11/linux-0.11/lib/dup.o
- /linux0.11/linux-0.11/lib/errno.c
- /linux0.11/linux-0.11/lib/errno.o
- /linux0.11/linux-0.11/lib/execve.c
- /linux0.11/linux-0.11/lib/execve.o
- /linux0.11/linux-0.11/lib/lib.a
- /linux0.11/linux-0.11/lib/Makefile
- /linux0.11/linux-0.11/lib/malloc.c
- /linux0.11/linux-0.11/lib/malloc.o
- /linux0.11/linux-0.11/lib/open.c
- /linux0.11/linux-0.11/lib/open.o
- /linux0.11/linux-0.11/lib/setsid.c
- /linux0.11/linux-0.11/lib/setsid.o
- /linux0.11/linux-0.11/lib/string.c
- /linux0.11/linux-0.11/lib/string.o
- /linux0.11/linux-0.11/lib/wait.c
- /linux0.11/linux-0.11/lib/wait.o
- /linux0.11/linux-0.11/lib/write.c
- /linux0.11/linux-0.11/lib/write.o
- /linux0.11/linux-0.11/lib/_exit.c
- /linux0.11/linux-0.11/lib/_exit.o
- /linux0.11/linux-0.11/mm/Makefile
- /linux0.11/linux-0.11/mm/memory.c
- /linux0.11/linux-0.11/mm/memory.o
- /linux0.11/linux-0.11/mm/mm.o
- /linux0.11/linux-0.11/mm/page.o
- /linux0.11/linux-0.11/mm/page.s
- /linux0.11/linux-0.11/mm/swap.c
- /linux0.11/linux-0.11/mm/swap.o
- /linux0.11/linux-0.11/tools/build
- /linux0.11/linux-0.11/tools/build.c
- /linux0.11/linux-0.11/tools/system
- /img/image-20241225120953264.png
- /img/image-20241225120957398.png
- /img/image-20241225121014019.png
- /img/image-20241225121148539.png
- /img/image-20241225121422512.png
- /img/image-20241225121554957.png
- /img/image-20241225121633565.png
- /img/image-20241225121637525.png
- /img/image-20241225122151326.png
- /img/image-20241225122213377.png
- /img/image-20241225122219755.png
- /img/image-20241225122236035.png
- /操作系统内核竞赛文档.pdf
- /changelog.txt
4855e6a3
Forked from lyx123 / project2608132
8 commits behind the upstream repository.

主要内容

  • 格式化Swap设备及挂载
  • 实现Swap.c相关函数,给Linux0.11增加更多虚拟地址功能
  • 测试程序

一,格式化Swap设备及挂载

1.格式化Swap设备

a. 第一个扇区用作MBR分区表 ,且第一个扇区最后有Magic Number: 55aa,表示分区有效

b. 接下来一页用作bit_map。Swap分区一共32MB,8092页。对应8092位,即1024个字节

c. 该页最后四个字节为签名SWAP

MBR由三部分构成: 1.主引导程序代码,占446字节 2.硬盘分区表DPT,占64字节,最多支持4个分区 3.主引导扇区结束标志AA55H

image-20241225120953264

image-20241225120957398

这里使用新添加的一块硬盘作为swap分区。

这块硬盘总大小64MB,这里只分了一个32MB的分区,作为Swap分区。

从下图的MBR表中可以看出,这一分区开始于0磁头,3扇区,0柱面。82标识Linux Swap分区。结束于15磁头,38扇区,107柱面。共1538107-2=65662。

逻辑上始于第2扇区,总共65662扇区。

image-20241225121014019

0x1fe处还有Magic Number: 0xaa55,表示MBR有效

从0x400开始,也就是第1kb处,即第三个扇区,是bitmap。

可以看出第1位已被标识成0,表示第一页已作它用,不能参与swap。

之后直到0x800都为1,表示可用,正好是1024字节,即8096位,对应8096个页面,也就是32MB的Swap分区。

超出32MB不可用,因此0x800之后到这一页结束,都置为0。

image-20241225121148539

注意在第一页的结尾有一个签名,SWAP,用来标识这个Swap设备。

2.Swap设备挂载到Bochs

bochsrc.bxrc中添加

ata0-slave:type=disk,path="$OS_PATH/newdisk.img",mode=flat,cylinders=204, heads=16, spt=38

204*16*38*512=63.5M(注意这里1MB=1000KB,生成.img文件时)

二,Swap.c相关函数

1.Linux初始化时读取Swap设备信息并输出

在hd.c函数里面的setup系统调用可以读取系统挂载的所有硬盘的信息。输出效果如下图:

读取信息并输出结束后,会调用init_swapping函数。

image-20241225121422512

2.Init_Swapping函数

输出所有硬盘的大小及分区后,就要执行swap分区的初始化。即读取swap分区的大小,看其大小是否符合规范。还要从swap分区第一页获得bitmap,并检查其是否合法

bitmap所在页需要满足以下条件:

  1. 页的最后四个字节为SWAP;

  2. bitmap的第一位为0,即不可用(被bitmap占用了);

  3. 超过swap_size的那些位应为0,即不可用。比如这里swap分区只有32M,对应8092个页,只需要8092位,也就是1024字节去表示。还剩3072字节,应该全置 为0,防止访问到32MB之外。

最后,该函数要统计一下swap分区可用的页数有多少。如果可用的页数为0,则该swap分区已不可用。

注意这里我们采用第二块硬盘的第一个分区作为swap分区,因此SWAP_DEV=0x306

image-20241225121554957

对于硬盘这类块设备,Linux0.11中只实现了ll_rw_block(),即按块读写的函数

对于Swap分区的读写是按页进行的,为了方便我们要先实现一个**ll_rw_page()**函数。即每次访问作为一个request,添加到硬盘队列中去,这个request每次读8个扇区,即4KB

image-20241225121633565

对于swap设备,它的设备号是固定的,因此我们可以用宏专门来进行swap设备的读写,减少参数

image-20241225121637525

  • get_swap_page() 扫描bitmap,若找到有一位是1,就把它置为不可用,并返回它的序号,表示找到了这一页free page
  • swap_free(int nr) 检查第nr位是否是0,如果是,就置为1并返回。否则报错。
  • swap_in() 从swap设备调一页到内存中
  • swap_out() 从将内存中的一页移出到swap设备中

Swap out()

该函数在get_free_page()中被调用。原来0.11中,get_free_page()是从16MB物理空间的尾部开始查找空闲的物理页。如果没有空闲的就返回0。但是这里有了swap功能,如果扫描一遍没找到空闲物理页,就要调用swap_out()函数,然后再次申请页面。

int swap_out(void)
{
    static int dir_entry = FIRST_VM_PAGE>>10;
    static int page_entry = -1;
    int counter = VM_PAGES;
    int pg_table;

    while (counter>0) {
        pg_table = pg_dir[dir_entry];
        if (pg_table & 1)
            break;
        counter -= 1024;
        dir_entry++;
        if (dir_entry >= 1024)
            dir_entry = FIRST_VM_PAGE>>10;
    }
    pg_table &= 0xfffff000;
    while (counter-- > 0) {
        page_entry++;
        if (page_entry >= 1024) {
            page_entry = 0;
        repeat:
            dir_entry++;
            if (dir_entry >= 1024)
                dir_entry = FIRST_VM_PAGE>>10;
            pg_table = pg_dir[dir_entry];
            if (!(pg_table&1))
                if ((counter -= 1024) > 0)
                    goto repeat;
                else
                    break;
            pg_table &= 0xfffff000;
        }
        if (try_to_swap_out(page_entry + (unsigned long *) pg_table)){
            printk("I'm swapping out at %u\n\r",page_entry + (unsigned long *) pg_table);
            return 1;
        }
            
    }
    printk("Out of swap-memory\n\r");
    return 0;
}

查找可被换出的页面过程如下:

从线性空间中的任务1的第一页开始往后找查找页目录,找最低位为1的项->查找页表,找到最低位为1的项-> 尝试换出try_to_swap_out()。若无法换出,继续查找如果成功换出,则将swap_nr左移1位存放到table_ptr中,以备将来使用

Try_to_swap_out():

在swap_out()函数中,找到的只是有可能被换出的页(有对应物理内存的页)。但这些页未必真的能换出,try_to_swap_out()还会做进一步检查

  • 再次检查page最低位是否为1
  • page大小是否越界
  • 如果该页未经修改过,则直接释放,而不用往swap设备上写
  • 如果该内存页未被使用(异常),或无法获得swap_nr(swap设备已满),则不能交换
int try_to_swap_out(unsigned long * table_ptr)
{
    unsigned long page;
    unsigned long swap_nr;

    page = *table_ptr;
    if (!(PAGE_PRESENT & page)) //page地址最右如果为1,说明是一个有效页表项(有对应的物理内存)。0x01&page
        return 0;
    if (page - LOW_MEM > PAGING_MEMORY)
        return 0;
    if (PAGE_DIRTY & page) { //只有当这个页面是被修改过时,才需要被换出。
                             //如果这个页面没被修改过,说明它肯定是从别处复制过来的,肯定还有副本。
                             //这时就不必换出,直接使用即可。
        page &= 0xfffff000;
        if (mem_map[MAP_NR(page)] != 1)
            return 0;
        if (!(swap_nr = get_swap_page()))
            return 0;
        *table_ptr = swap_nr<<1;  //swap_nr左移一位,使最右位为0。这样table_ptr最低位也为0,
                                  //系统就会知道这一页表项是没有对应物理内存的。
                                  //*table_ptr中储存的是原来那页在swap分区中的编号*2。
        invalidate();
        write_swap_page(swap_nr, (char *) page);
        free_page(page);
        return 1;
    }
    *table_ptr = 0;
    invalidate();
    free_page(page);
    return 1;
}

Swap_in():

在发生缺页中断时被调用。Swap_out()时已将该页在swap设备上的页码储存在table_ptr中。通过它可以获得swap_nr,通过read_swap_page()将其读回内存。读回后,要修改对应的bitmap位。还要修改table_ptr成新的物理内存地址,并将标志位置为已修改过。

三,测试程序

不断malloc申请内存,并往内存中写入任意内容(如果不写的话,由于写时复制机制,系统不会真的分配物理内存)

在原始的Linux0.11系统上,申请2960页内存会发生oom错误 image-20241225122151326

添加Swap后,运行效果如下:申请了2960页,超出16MB,发生换出操作,在执行换出操作时打印了待换出的物理内存地址

image-20241225122213377

image-20241225122219755

一次换入过多,会发生奇怪的错误

image-20241225122236035

四,目录

├── bochs                   Bochs模拟器相关文件
│   ├── BIOS-bochs-latest   Bochs BIOS镜像文件
│   ├── bochs-dbg           Bochs调试版本
│   ├── bochs-gdb           支持GDB调试的Bochs版本
│   ├── bochsrc-gdb.bxrc    GDB调试用的Bochs配置文件
│   ├── bochsrc.bxrc        默认Bochs配置文件
│   ├── bochsrc.bxrc~       Bochs配置文件备份
│   └── vgabios.bin         VGA BIOS文件
├── bochsout.txt            Bochs运行输出日志
├── 操作系统内核竞赛文档.pdf  竞赛文档
├── dbg-asm                 汇编调试文件
├── dbg-c                   C语言调试文件
├── gdb                     GDB调试相关文件
├── gdb-cmd.txt             GDB命令脚本
├── hdc                     硬盘文件目录
│   └── umounted            未挂载的硬盘文件
├── hdc-0.11.img            Linux 0.11系统硬盘镜像
├── linux-0.11              Linux 0.11源码目录
│   ├── Image               编译生成的内核镜像
│   ├── Makefile            主构建文件
│   ├── System.map          内核符号表
│   ├── boot                启动引导代码
│   │   ├── bootsect        引导扇区代码
│   │   ├── bootsect.o      引导扇区目标文件
│   │   ├── bootsect.s      引导扇区汇编代码
│   │   ├── head.o          初始化目标文件
│   │   ├── head.s          初始化汇编代码
│   │   ├── setup           引导程序代码
│   │   ├── setup.o         引导程序目标文件
│   │   └── setup.s         引导程序汇编代码
│   ├── fs                  文件系统相关代码
│   │   ├── Makefile        文件系统模块构建文件
│   │   ├── *.c             文件系统功能实现(如inode、读写、打开文件等)
│   │   ├── *.o             文件系统模块目标文件
│   │   └── ...             文件系统代码的其他支持文件
│   ├── include             头文件目录
│   │   ├── asm             汇编相关头文件
│   │   ├── linux           Linux内核头文件
│   │   └── sys             系统调用相关头文件
│   ├── init                内核初始化代码
│   │   ├── main.c          内核初始化主程序
│   │   └── main.o          内核初始化目标文件
│   ├── kernel              内核核心功能实现
│   │   ├── Makefile        内核模块构建文件
│   │   ├── blk_drv         块设备驱动
│   │   ├── chr_drv         字符设备驱动
│   │   ├── math            数学仿真模块
│   │   ├── *.c             核心功能实现(如进程调度、系统调用等)
│   │   ├── *.o             核心模块目标文件
│   │   └── ...             其他内核模块
│   ├── lib                 库函数实现
│   │   ├── Makefile        库函数模块构建文件
│   │   ├── *.c             标准库函数实现(如malloc、字符串处理等)
│   │   └── *.o             标准库函数目标文件
│   ├── mm                  内存管理模块
│   │   ├── Makefile        内存管理模块构建文件
│   │   ├── memory.c        内存管理核心代码
│   │   ├── swap.c          交换分区管理代码
│   │   ├── *.o             内存管理模块目标文件
│   │   └── ...             内存管理的其他支持文件
│   ├── tags                代码标签文件,用于代码导航
│   └── tools               工具目录
│       ├── build           内核构建工具
│       ├── build.c         内核构建工具源码
│       └── system          系统构建工具
├── mount-hdc               挂载硬盘脚本
├── newdisk.img             新硬盘镜像文件
├── run                     启动Linux 0.11的脚本
├── rungdb                  使用GDB调试Linux 0.11的脚本
└── swaptest.c              测试交换分区功能的代码