如何在windows上编译和运行xv6

如何在windows上编译和运行xv6,第1张

首先编译xv6涉及的工具包括gcc,binutils,make,qemu。

xv6需要能生成elf32格式的可执行文件的工具链,好在windows下已经有了mingw32这个gcc在windows下的移植,

这样用mingw32编译一套在windows下运行的i386-none-elf交叉工具链成为可能。

Make和qemu也是如此,这里需要说明的是默认网上下载的qemu可执行文件很可能是不带有gdb调试功能的,

这也是需要重新自己编译qemu的原因之一,第二个原因是qemu默认的输入输出会被定向到两个文本文件,

直接后果是xv6的uart将无法使用,自己编译qemu解决上述两点。

接下来是修改makefile文件,这里同时涉及dd,sign.pl,vectors.pl,mkfs。

dd在这里的作用是将bootblock和kernel两个文件组合构建xv6.img镜像,sign.pl是在bootblock添加0xaa55引导标记,

vectors.pl是生成vectors.S文件,mkfs是构建xv6根文件系统镜像fs.img用的。

我编写了wd.c对应dd,sign.c对应sign.pl,vectors.S在linux构建时直接复制了,mkfs.c也需要修改。

wd.c

[cpp] view plain copy

#include <stdio.h>

int main(int argc, char *argv[])

{

char buf[512]

int n

FILE *fdin

FILE *fdout

fdout = fopen(argv[1], "wb+")

fdin = fopen("bootblock", "rb")

for(n = 1n >0) {

n = fread(buf, 1, 512, fdin)

fwrite(buf, 1, n, fdout)

}

fclose(fdin)

fdin = fopen("kernel", "rb")

for(n = 1n >0) {

n = fread(buf, 1, 512, fdin)

fwrite(buf, 1, n, fdout)

}

fclose(fdin)

fclose(fdout)

return 0

}

sign.c

[cpp] view plain copy

#include <stdio.h>

int main(void)

{

FILE *fd

char buf[2]

buf[0] = 0x55

buf[1] = 0xaa

fd = fopen("bootblock", "rb+")

fseek(fd, 510, SEEK_SET)

fwrite(buf, 1, 2, fd)

fclose(fd)

return 0

}

mkfs.diff

[cpp] view plain copy

19c19

<int fsfd

---

>FILE *fsfd

34a35,39

>

>#define bzero(s,n) memset(s,0,n)

>#define bcopy(src,dest,n) memmove(dest,src,n)

>#define index(a,b) strchr(a,b)

>

61c66,67

< int i, cc, fd

---

> int i, cc

> FILE *fd

75,76c81,82

< fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666)

< if(fsfd <0){

---

> fsfd = fopen(argv[1], "wb+")

> if(fsfd == NULL){

118c124

<if((fd = open(argv[i], 0)) <0){

---

>if((fd = fopen(argv[i], "rb+")) == NULL){

137c143

<while((cc = read(fd, buf, sizeof(buf))) >0)

---

> while((cc = fread(buf, 1, BSIZE, fd)) >0)

140c146

<close(fd)

---

>fclose(fd)

158,159c164,165

< if(lseek(fsfd, sec * 512L, 0) != sec * 512L){

<perror("lseek")

---

> if(fseek(fsfd, sec * 512L, SEEK_SET) != 0){

>perror("fseek")

162,163c168,169

< if(write(fsfd, buf, 512) != 512){

<perror("write")

---

> if(fwrite(buf, 1, 512, fsfd) != 512){

>perror("fwrite")

204,205c210,211

< if(lseek(fsfd, sec * 512L, 0) != sec * 512L){

<perror("lseek")

---

> if(fseek(fsfd, sec * 512L, SEEK_SET) != 0){

>perror("fseek")

208,209c214,215

< if(read(fsfd, buf, 512) != 512){

<perror("read")

---

> if(fread(buf, 1, 512, fsfd) != 512){

>perror("fread")

mkfs命令是linux下的一个磁盘维护命令,它主要有一个功能,具体介绍如下:mkfs命令可以用来在设备上建立Linux文件系统,即在特定分区上建立文件系统,也就是指硬盘分区。说明:mkfs命令一般只能是Linux系统下可以使用的各种文件系统构建器的前在/sbin、/sbin/fs、/sbin/fs.d、/etc/fs、/etc/fs等多个目录当中搜寻指定于文件系统的生成器,最后会在PATH环境变量中列出的目录中搜寻。

如何从零开始写一个简单的 *** 作系统

看了这个:从零开始写一个简单的 *** 作系统 求指教。

知乎用户 学生生涯只剩半年。

548 人赞同

终于可以来回答这道题了……

一年多前,也就是大一下学期末的时候,我看到这个问题下 @fleuria 叔的答案,然后看了 F 叔给的这个链接 基于 Bochs 的 *** 作系统内核实现 ,当然是什么都看不懂,除了惊诧之外也了解了一件事情:一个人写一个简单的 *** 作系统内核是一件非常帅气并且可行的事情。

于是我开始写了,那时候我的水平大概是:只会做 C 语言的习题,编译的话只知道按 F9,汇编知道常见的指令,另外会一点点的 Win 32 编程,能流畅使用 Windows。

一开始我找了《30 天自制 *** 作系统》来看,每天看书,然后把从书里把代码打出来,一次一次地编译运行。因为要同时写汇编和 C,所以从那时候起就开始用 vim。

在啃完了差不多半本书后,开始觉得没意思了……因为觉得作者为了让内容更简单而省略了太多细节。也看了于渊的《Orange‘s 一个 *** 作系统的诞生》,依然没看下去:汇编用得太多了。期间也曾斗胆发邮件给 F叔,然后他推荐了 Bran's Kernel Development Tutorial 这个教程,于是我就从这教程重新开始了: 「30天自制 *** 作系统」 Stop &「OS67 」 Start

那时候大概是大二上学期,于是在 github 上又开了一个 repo,一开始在 Windows 下开发,后来又切换到了 Linux 下,因为 Bran's 用的 bootloader 是 Grub,不符合我的初衷,所以就自己写了一个,之后便跟一路教程写,跨过了保护模式这道坎,完成了基本的设备驱动。

在完成 Bran's 后,我又部分参考了 写一个 *** 作系统内核有多难?大概的内容、步骤是什么? - To浅墨的回答 中推荐的:hurley25/hurlex-doc · GitHub 文档,完成了一些简单的调试函数和库函数,printk 和内存分配。

事实证明,尽早写好调试函数诸如 panic, assert 和 printk 是非常重要的。 大量地使用有助于你尽快地发现 bug (当然前提是这些函数本身不能有 bug)。

看完了 hurlex-doc 该看的部分后,很长一段时间了都不知道该干嘛好,模仿 hurlex-doc 里的内核线程切换也一直出错。这一情况一直持续到我开始读 Xv6, a simple Unix-like teaching operating system 。

如果你去看知乎关于「自制内核」的问题,你会发现 xv6 被反复地提及并推荐,事实上它非常值得被推荐:这是我读完大部分代码之后真切体会到的。

之前的 Bran‘s 和 hurlex-doc 的篇幅都比较小,我是在电脑和 kindle 上看完的,xv6 相对来说代码量比较大,有 9000+ 行和一份文档,之后我又找到了这个:ranxian/xv6-chinese · GitHub xv6 文档的中文译版,所以我就去花了十二块钱学校打印店打印了一份中文文档和一份代码。这又是一个正确的决定,让我不必对着电脑就能看代码。

在之后的时间里,我先读了 xv6 中文件系统相关的部分,然后改写它的代码为我的内核添加了一个 类似 Minix 的文件系统。 然后几乎又照抄了其中了进程调度的部分(做了部分简化),又在原来的代码基础上为添加 *** 作系统的接口,接着写用户程序,过程几乎是「一路顺风」。看 xv6 的那段时间也经常是处于醍醐灌顶的状态。

最后我终于在差不多一个月前完成了这个简陋的 *** 作系统内核:

LastAvenger/OS67 · GitHub (没错其实我是来骗 star 的)

历时一年,一路点亮了不少技能树(虽然都点得不好),这样算是「从零开始写一个简单的 *** 作系统」么? 跟进一步说,有谁不是从零开始的呢?所以想做的话,现在就开始做好了。

这是被「翻烂」了的 xv6 源代码和中文文档(其实是放书包里被磨烂了)

「故事」讲完了,接下来说一点经验之谈吧……

* 知乎上总是有人在讨论「做一个玩具编译器和做一个玩具内核何者更有趣」之类的问题,然后总有各种大V 跳出来说内核有多 dirty 而编译器多 clean,事实上除了 CPU 上的几个表因为历史原因长得恶心一点,内核并没有什么特别 dirty 的地方,另外,想做点什么打发时间,不过是两个代码量稍多的入门项目,有什么好纠结的?

* 写内核的过程中,你会接触到一些这辈子大概只会用到一次的知识,A20 线已经成为历史,日常的编程里面也不需要你懂得 GDT IDT 的结构。但是单凭内核主要部分部分(文件系统,进程,内存)给你带来的知识而言,这点冗余是值得的。

* 尽早实现调试函数并大量使用,善于利用 bochs 的内置调试器,能省下你不少时间。

* 有时候觉得书里的做法非常奇怪,你觉得你有更好的做法,一般是你想错了。(当然只是一般)

* 上面说看 xv6 一路顺风是假的,20% 时间在抄代码,80% 的时间用来调试。

* 对我这种能力一般的人来说,「写内核」只是好听的说法,正确的说法是「抄内核」。当然,就算是抄一个,也算是受益匪浅了。

* 抄 xv6 的好处在于,即使你的代码出错了,你可以坚信,正确的答案肯定在 xv6 的代码里,或许只是你还没理解透而已,只要不断地看和理解,你就离正确的道路越来越近。

最后,感谢 @fleuria 在微博和邮件里的多次帮助, @To浅墨 的 hurlex-doc 文档,鲜染同学翻译的 xv6 中文文档, @郭家华 完美地解答了我一开始的疑问,让我在内核中得以使用 C 语言。

在 #archlinuxcn 频道里也得到了很多人的帮助。

发布于 2015-11-09

邱永臣 喜剧演员,兼开发工程师

890 人赞同

大二的时候,老师(中山大学万海)对我们说:“如果有谁能自己写一个内核出来,那么,他平时可以不来听课,也不用做平时作业,做出来还能加分,怎么样,有没有人有兴趣?”

和老师一番讨价还价之后,我成为全年级几百号人里唯一一个自己写内核/整个学期都不去教室听课/任何作业都不做的那个人(代表着我的身边将没有可以提供参考的人,任何资料都只能自己找)。

一开始买了《30天自制 *** 作系统》,上面写着需要软盘还有其它的模拟器,我的初衷是写一个可以烧在真机上一按开机键就能跑起来的那种,所以看了几页后就丢开了。后来又找了国人写的一本,也不是特别符合,也丢开了。

这时我看到了那本教材(俗称绿宝书),约莫800页。之后的两个星期里,我每天泡图书馆,以每小时10页的速度读完了它,在上面乱涂乱画了许多标记。800页的英文书,我从中学到了大量的基本概念(线程进程,内存算法,寻址方式等等)。

接着我寻思直接从网络上而不是从书上寻找资料,TA师兄给我提供了一个OS Development,我照着上边的例子,写了数以千记的汇编代码,习得了汇编技能。

此时,我具备基本的概念知识,对程序的语言也已经理解,知道了虚拟机的调试方法,差的,就只有对内核整体是如何协作不太明白。于是我去找来老师用于教学的PintOS,找来MIT那个项目的代码,还有国内一个高校自制的OS(是几个研究生一起写的),仔细研究了一遍,最后开始写代码。

在那个学期里,我放弃了LOL,一心看代码,写内核,写各种模块,将过程记录在博客上,花了三个月的时间,最终写出一个具备terminal的内核(文件系统没写好,时间不够),可以跑命令,运行函数,管理内存和进程,处理中断。

--------------------------

这个Tittle非常好,衷心希望不要因为莫须有的理由封杀。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7996383.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-12
下一篇2023-04-12

发表评论

登录后才能评论

评论列表(0条)

    保存