nproc
输出cpu计算单元数量为12
按照实验主页先按默认选项编译,文件大小为17M
剪了网络,文件系统,各种驱动,不需要安全模块,不需要一些高级算法,多核支持等,到了6MiB以下(6MiB=6291456 Bytes, Image size=6203904 Bytes)
按照"Operating System Concepts"中的init
进程的fork()
函数,并且调用execl()
创建子进程并且依次执行1,2,3程序,wait()
让父进程等待,调用exit(1)
退出子进程
仿照实验主页中/dev/null
字符设备的创建,以及mknod()
的manual选择S_IFCHR | S_IRUSR | S_IWUSR
mode,由已知,对/dev/ttyS0
,makedev(4. 64)
,对/dev/ttyAMA0
相应创建,对/dev/fb0
,makedev(29, 0)
...不知道讲义里的据树莓派官网的UART配置介绍,默认情况下启动UART0,类型为PL011,对应于ttyS0
与ttyAMA0
的或关系是什么意思,ttyS0
不行,也许是内核模块里没有支持ttyS0
/dev/ttyAMA0
,要使用/dev/ttyS0
,即使用miniUART,需要进行相应的配置。默认状态下enable_uart=1
,使用UART0
使用循环来防止kernel panic
- Makefile
- $@: 目标文件
- $^: 所有依赖文件
- $<: 第一个依赖文件
make boot.bin
make loader.bin
make kernel.bin
make bootloader.img
make qemu
make clean
和make cleanall
挺好,然而我不清理
非注释部分是我选择的,其他部分稍作了解,希望也能够帮我改一改,辛苦了
- 1.
xor ax, ax
在将ax
与其本身异或清零然后保存到ax寄存器中,好处是计算比数据移动要更快,更快的清零,在指令的大小和数量方面最快 - 2.
jmp $
中$
表示取当前指令所在的地址,jmp $
相当于不断将该指令的地址存入PC,形成死循环。只有当中断发生时,才会转去执行中断服务程序
- 3.
[es:di]
es*16+di- 4.
boot.asm
文件前侧的org 0x7c00
的用处是定义boot
代码的绝对地址(比如在定义中断向量表的时候需要定义地址)- 5.
times 510 - ($-$$) db0
是在下面的代码中重复填入0共510-(当前指令地址-当前部分起始地址)
次,原因是boot.asm
最后的boot sector mark
中是boot signature
,BIOS在boot sector
偏移510,511的地方找0x55
和0xAA
,通过times
操作填充0可以方便在偏移510,511的位置写boot signature
- 1.
I am OK
只要在loader的log_info GetMemStructOkMsg
后面调用宏log_info IamOK, <字符串长度,不包括\0>, 4(第四行)
即可,当然要在GetMemStructOkMsg
下面写IamOK: db 'I am OK!'
- 2.确定软盘可启动:通过
fat12_find_file_in_root_dir
来实现,如果找到了,就会进行后续的加载extry等操作,如果没有找到,就会失败,跳转到not_found
。在fat12_find_in_root_dir
中,主要通过对Sector
和entry
的循环实现顺序查找,通过比对文件名来实现- 3.为什么
boot.asm
2.之后可以继续执行loader.asm
?原因是boot.asm
中有jmp LoaderBase:LoaderOffset
指令,而loader.asm
的代码开始地址就是0x10000
,所以jmp
会跳转到LoaderBase*16+LoaderOffset
的位置,刚好就是0x1000*16+0x0000 = 0x10000
- 4.
boot.asm
与loader.asm
隔开的原因: - 同一个文件不能存在两个org
,这样只能用times
写,还要计算多少个0,很麻烦 - 如果将两个代码合在一起,在计算地址的时候就会很复杂,比如要修改boot
部分的一点代码,可能就要涉及到很多的地址计算的修改。将两个代码在地址上分开方便维护,更新,修改。另外boot
部分与loader
部分对不同的硬件,不同的文件系统等,都要进行相应的修改,如果不分开,就很难维护,不如用jmp
指令跳转来的方便 - 还有是放在两个文件里,标签可以重叠不会有影响,因为两个分开编译,方便写程序
- 在题目的范畴下,
Linux
应该主要指的是内核,它并不是一个完整的操作系统,而Ubuntu
,Debian
,Fedora
,ArchLinux
指Linux发行版。一个linux发行版除了包含linux内核外,通常还包含一系列GNU工具和库,一些附带软件,桌面系统等。不同的发行版用起来感觉可能完全不同,例如Arch
系和Debian
系的包管理器就有很大区别,在系统安装上也有很大差异,但是其内核是基本一致的(对不同发行版还是有细微差异)(参考了Linux101讲义) - 不需要,因为我们在
qemu
上模拟,不需要SD卡。指导意义:init程序需要的如tty输出模块要保留,其他的一些可选模块基本都可以删去 - 树莓派启动阶段(BCM2837 based)
- 读取OTP(one-time programming)内存块决定哪种模式被启用
- SoC上ROM中的
bootloader
执行,挂在SD卡FAT32
分区 bootloader
从SD卡上检查GPU固件,将固件写入GPU,随后启动GPU- GPU启动后检索config.txt, fixup.dat,根绝其内容设置CPU参数和内存分配,然后加载用户代码,启动CPU
- 然后CPU执行内核程序
- config中写了
enable_uart=1
,不是只能用miniUART了吗?
qemu-user
中包含了qemu-arm
,所以可以执行arm64
的busybox
- 具体过程:
- 在安装
qemu-user
的过程中会自动安装qemu-user-binfmt
- 安装了之后在
/proc/sys/fs/binfmt_misc
中就有很多条目,这些条目代表着各种指令的解释器,在我这里qemu-arm
的解释器就是/usr/bin/qemu-arm
- 当直接执行
./busybox
时,kernel发现是ARM的elf格式,然后就使用/usr/bin/qemu-arm
解释器(x86),来跑busybox,在本机上跑的实际是/usr/bin/qemu-arm
这个解释器
- 在安装
qemu-user
和qemu-system
的区别就是qemu-user
是运行单个程序文件,只有UserSpace emulation
,而qemu-system
是full system emulation
,包括UserSpace emulation
,kernel emulation
和hardware emulation
,qemu-user
相对更快
- 具体过程:
exec another process in one process
希望改完能提点issue