TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Kernel 101 – Let’s write a Kernel

435 pointsby slashdotaccountabout 11 years ago

21 comments

akkartikabout 11 years ago
I got this running on qemu by cannibalizing a tiny bit of code from xv6 (<a href="http://pdos.csail.mit.edu/6.828/2012/xv6.html" rel="nofollow">http:&#x2F;&#x2F;pdos.csail.mit.edu&#x2F;6.828&#x2F;2012&#x2F;xv6.html</a>) to replace the GRUB dependency. After cloning and building mkernel according to its instructions:<p><pre><code> $ git clone git:&#x2F;&#x2F;pdos.csail.mit.edu&#x2F;xv6&#x2F;xv6.git $ cd xv6 $ make </code></pre> Now you should be able to run xv6 by itself:<p><pre><code> $ path-to-qemu&#x2F;x86_64-softmmu&#x2F;qemu-system-x86_64 -serial mon:stdio -hdb fs.img xv6.img -m 512 </code></pre> To run mkernel on qemu, we&#x27;ll replace xv6&#x27;s kernel with mkernel&#x27;s:<p><pre><code> $ dd if=&#x2F;dev&#x2F;zero of=mkernel.img count=10000 $ dd if=bootblock of=mkernel.img conv=notrunc $ dd if=..&#x2F;mkernel&#x2F;kernel of=mkernel.img seek=1 conv=notrunc </code></pre> Now you can boot up the <i>mkernel.img</i> rather than <i>xv6.img</i>:<p><pre><code> $ path-to-qemu&#x2F;x86_64-softmmu&#x2F;qemu-system-x86_64 -serial mon:stdio -hdb fs.img mkernel.img -m 512 </code></pre> (Based on xv6 at hash ff2783442ea2801a4bf6c76f198f36a6e985e7dd and mkernel at hash 42fd4c83fe47933b3e0d1b54f761a323f8350904. Ping me if you have questions; email in profile.)
评论 #7590831 未加载
grahamedgecombeabout 11 years ago
There&#x27;s a slight problem in this tutorial in that it assumes ESP (the stack pointer) will be defined by the boot loader to point to an appropriate location for the stack. However, the Multiboot standard states that ESP is undefined [1], and that the OS should set up its own stack as soon as it needs one (here the CALL instruction uses the stack, and the compiled C code may well too).<p>An easy way to solve this is to reserve some bytes in the .bss section of the executable for the stack by adding a new section in the assembly file:<p><pre><code> [section .bss align=16] resb 8192 stack_end: </code></pre> Then before you make use of the stack (between `cli` and `call kmain` would be appropriate in this case), you need to set the stack pointer:<p><pre><code> mov esp, stack_end </code></pre> [1]: <a href="https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Machine-state" rel="nofollow">https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;grub&#x2F;manual&#x2F;multiboot&#x2F;multiboot...</a>
exDM69about 11 years ago
This seems like a good start but it&#x27;s worth noting that it isn&#x27;t guaranteed to work correctly.<p>The problem is that the control is passed to C code with no stack space set up. It works out of pure luck because the compiler has decided to keep all variables in registers and changing your C compiler flags might make this fail in interesting ways.<p>Another thing that is missing is clearing the .BSS section before passing control to the C code. It&#x27;s not used at the moment, though.<p>I am pointing these things out because in my own Ring—0 programming projects I spent a lot of time debugging some failures related to stack space and an un-initialized BSS section.
评论 #7590790 未加载
bebopabout 11 years ago
This is a great resource for anyone who would like to take this further: <a href="http://wiki.osdev.org/Expanded_Main_Page" rel="nofollow">http:&#x2F;&#x2F;wiki.osdev.org&#x2F;Expanded_Main_Page</a><p>In particular, setting up interrupt handlers, paging, and getting a PIC setup is pretty neat.
boulderdashabout 11 years ago
If anybody is doing this, let me share some words of advice based on experience.<p>Please use a virtual machine instead of doing this on your primary machine. You eliminate the risk of messing up your machine. Also, if you setup the VM properly, you get a debugger.
评论 #7590834 未加载
评论 #7589075 未加载
评论 #7589685 未加载
AdrianoKFabout 11 years ago
Looks great, will keep an eye on this!<p>I also really enjoyed James Molloy&#x27;s OS kernel development tutorial at <a href="http://www.jamesmolloy.co.uk/tutorial_html/" rel="nofollow">http:&#x2F;&#x2F;www.jamesmolloy.co.uk&#x2F;tutorial_html&#x2F;</a>, which takes you from &quot;Hello World&quot; to some real toy OS kernel implementation.
评论 #7590806 未加载
评论 #7588911 未加载
mbillie1about 11 years ago
Very cool. I personally (as a developer without a CS background) find these sorts of posts wonderfully interesting, even if this kernel, as pointed out in this thread, lacks a lot of what a normal kernel does. I&#x27;d love to see one of these for a compiler!
评论 #7590913 未加载
评论 #7588970 未加载
dkarapetyanabout 11 years ago
I really like the new HN. Quality of articles is way up.
评论 #7588892 未加载
ahelwerabout 11 years ago
Neat read so far! Not done yet, but I think I&#x27;ve found a small error in kernel.c: the attribute byte of the characters in &quot;my first kernel&quot; should be set to 0x02, not 0x07.<p>edit: I misread. 0x07 is intentional, 0x02 was mentioned as an alternative. Good post!
评论 #7588592 未加载
评论 #7588514 未加载
tbrockabout 11 years ago
This was fantastic. My only question is, how does one gain knowledge of the required x86 hardware specifics he mentions? I don&#x27;t know where to begin looking to uncover these sorts of things:<p><pre><code> - The x86 CPU begins execution at the physical address [0xFFFFFFF0] - The bootloader loads the kernel at the physical address [0x100000] - The BIOS copys the contents of the first sector to physical address [0x7c00] </code></pre> Is there an x86 instruction manual or is this sort of thing passed down through generations of engineers?
评论 #7590739 未加载
评论 #7590253 未加载
aarenabout 11 years ago
Can anyone give me an idea how much different this would be for 64bit? Do I just change the nasm directive to `bits 64`?
评论 #7589191 未加载
评论 #7590801 未加载
评论 #7589170 未加载
deathanatosabout 11 years ago
I kinda wish some of the FS utilities were better. Despite FUSE, mounting a block device (like, disk image) as a non-root user is tough, so writing to an image with actual partitions&#x2F;FS on it is difficult, especially to script, especially if you don&#x27;t want to sudo in a build script. losetup on a disk image doesn&#x27;t (to my knowledge) detect partitions… for reasons unknown to me.<p>Bootsectors are similar. You can&#x27;t just install grub to a disk image. (You have to losetup it, at the very least, which implies root. Why can&#x27;t I just install to a file?)<p>You want a script&#x2F;build system that allows you, at the very least, to:<p>1. Code. 2. Run build system&#x2F;script. 3. Fire up qemu or similar.<p>You can&#x27;t be rebooting. Ideally, it&#x27;d be great to do this in userspace.<p>That said, if you&#x27;re starting out, just do [boot sector] + [kernel] = tada image until you need to do otherwise. (Really, do whatever works and is easy.)<p>That said, I&#x27;ve found a few somewhat helpful tools.<p>fuseloop[1] takes a file and offset&#x2F;size, and exposes a single file. If you have a partitioned disk image, then you can feed it the partition offset, and it gives you back something you can format as an FS. (e.g., you can run ext2fs on.)<p>Then there&#x27;s fuse.ext2[2], which mounts an ext2 FS on FUSE, so non-root usable again. Note that I&#x27;m linking to my fork of it, since the original didn&#x27;t build for me, but I didn&#x27;t write it. (Which I fixed, and sent a pull request, but never heard back.)<p>Finally — and sorry to peddle my own stuff again — I wrote a Python library for dealing with the MBR.[3] I use it to figure out offsets and sizes in a disk image.<p>I&#x27;ve had a bit of fun writing a boot loader, and I&#x27;ve managed to get it to load up its stage 2 and switch to 32-bit pmode. Had a fun error where a division instruction was throwing things into a triple fault; see [4] if you want to see how a division instruction can fail <i>without</i> dividing by zero (which was the first thing I checked). The disk layout is currently:<p><pre><code> [boot sector] [stage 2] [kernel] [ partitions, FS, real data, etc. ] </code></pre> stage2&#x27;s size is hard coded into the first sector of stage 2 (into itself), and the kernel&#x27;s location and size will be similarly hard coded into it as well. (When I get there. Disks in pmode are different, as you can&#x27;t just have the BIOS do all the work for you, sadly!) And by hard-coded, a build script calculates and just re-writes a few bytes.<p>[1]: <a href="https://github.com/jmattsson/fuseloop" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;jmattsson&#x2F;fuseloop</a><p>[2]: <a href="https://github.com/thanatos/fuse-ext2-fakeFS" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;thanatos&#x2F;fuse-ext2-fakeFS</a><p>[3]: <a href="https://github.com/thanatos/pymbr" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;thanatos&#x2F;pymbr</a><p>[4]: <a href="http://stackoverflow.com/questions/21212174/why-cant-i-step-over-this-div-instruction" rel="nofollow">http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;21212174&#x2F;why-cant-i-step-...</a>
评论 #7590710 未加载
tpushabout 11 years ago
I have done the same, sort of, only eschewing BIOS for UEFI and thus getting straight to Long Mode :-).<p>It&#x27;s pretty basic, currently just boots up and prints the memory map.<p>It&#x27;s written in C++11 with the aim to be as clear as possible: <a href="https://github.com/thasenpusch/simplix" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;thasenpusch&#x2F;simplix</a> Have a look :-).
jonalmeidaabout 11 years ago
I just finished an Operating Systems final today and the entire class was conceptual and learning fundamentals, while I craved to get my hands dirty and actually try to make a simple OS.<p>I&#x27;ll definitely be playing around with this. Thanks!
anarionabout 11 years ago
Why kernel tutorials always say they need nasm. Gcc already comes with an assembler so simply use it instead of installing other softwares. And if you prefer intel syntax simply add &quot;.intel_syntax;&quot;
zenbowmanabout 11 years ago
Looks great, looking forward to dive into this.
acomjeanabout 11 years ago
Why C?<p>I&#x27;m just curious if another language can be used. (c++, go, rust).
评论 #7589049 未加载
评论 #7589050 未加载
评论 #7589670 未加载
评论 #7590977 未加载
tsenkovabout 11 years ago
Awesome read, thanks.
kyberiasabout 11 years ago
I&#x27;m not exactly Linus Torvalds but I&#x27;m pretty sure a program that prints one line of text is not &quot;a kernel&quot;. :)
评论 #7588584 未加载
评论 #7588622 未加载
评论 #7589663 未加载
评论 #7589401 未加载
评论 #7591057 未加载
评论 #7588776 未加载
评论 #7588583 未加载
评论 #7588570 未加载
whydoabout 11 years ago
The first question is:<p>Why?<p>We already have a whole bunch of operating systems, many of them free.<p>One of the frequent problems with a lot of free&#x2F;open source software folks is that they lack direction. This type of thing where we do stuff just to do stuff probably won&#x27;t fly in one of the leading tech companies.<p>Why don&#x27;t you figure out a real problem people have and look for ways to solve that, instead of just doing random &quot;interesting&quot; stuff that wastes people&#x27;s valuable time?
评论 #7601978 未加载
aortegaabout 11 years ago
Great! except that to be called a kernel it&#x27;s missing just a process manager, memory manager, filesystem, process separation and hardware abstraction. Yeah I&#x27;m <i>that</i> guy, down vote me as you wish, the article is still wrong.<p>It&#x27;s a way to load a ring-0 application into grub. Pretty cool, but not a kernel.
评论 #7588855 未加载
评论 #7589349 未加载
评论 #7588930 未加载