|
在下面的post中,Linus描述了自己开发OS的过程。。。<br />------------------------------------------------------<br />From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds)<br />Newsgroups: comp.os.linux<br />Subject: Re: Writing an OS - questions !!<br />Message-ID: <1992May5.075817.15984@klaava.Helsinki.FI><br />Date: 5 May 92 07:58:17 GMT<br />References: <10685@inews.intel.com><br />Organization: University of Helsinki<br />Lines: 136<br /><br />In article <10685@inews.intel.com> nani@td2cad.intel.com (V. Narayanan) writes:<br />><br />>Hi folks,<br />> For quite some time this 'novice' has been wondering as to how one goes<br />>about the task of writing an OS from 'scratch'. So here are some questions,<br />>and I would appreciate if you could take time to answer 'em.<br />Well, I see someone else already answered, but I thought I'd take on the<br />linux-specific parts. Just my personal experiences, and I don't know<br />how normal those are.<br />>1) How would you typically debug the kernel during the development phase?<br />Depends on both the machine and how far you have gotten on the kernel:<br />on more simple systems it's generally easier to set up. Here's what I<br />had to do on a 386 in protected mode.<br />The worst part is starting off: after you have even a minimal system you<br />can use printf etc, but moving to protected mode on a 386 isn't fun,<br />especially if you at first don't know the architecture very well. It's<br />distressingly easy to reboot the system at this stage: if the 386<br />notices something is wrong, it shuts down and reboots - you don't even<br />get a chance to see what's wrong.<br />Printf() isn't very useful - a reboot also clears the screen, and<br />anyway, you have to have access to video-mem, which might fail if your<br />segments are incorrect etc. Don't even think about debuggers: no<br />debugger I know of can follow a 386 into protected mode. A 386 emulator<br />might do the job, or some heavy hardware, but that isn't usually<br />feasible.<br />What I used was a simple killing-loop: I put in statements like<br />die:<br />jmp die<br />at strategic places. If it locked up, you were ok, if it rebooted, you<br />knew at least it happened before the die-loop. Alternatively, you might<br />use the sound io ports for some sound-clues, but as I had no experience<br />with PC hardware, I didn't even use that. I'm not saying this is the<br />only way: I didn't start off to write a kernel, I just wanted to explore<br />the 386 task-switching primitives etc, and that's how I started off (in<br />about April-91).<br />After you have a minimal system up and can use the screen for output, it<br />gets a bit easier, but that's when you have to enable interrupts. Bang,<br />instant reboot, and back to the old way. All in all, it took about 2<br />months for me to get all the 386 things pretty well sorted out so that I<br />no longer had to count on avoiding rebooting at once, and having the<br />basic things set up (paging, timer-interrupt and a simple task-switcher<br />to test out the segments etc).<br />>2) Can you test the kernel functionality by running it as a process on a<br />> different OS? Wouldn't the OS(the development environment) generate<br />> exceptions in cases when the kernel (of the new OS) tries to modify<br />> 'priviledged' registers?<br />Yes, it's generally possible for some things, but eg device drivers<br />usually have to be tested out on the bare machine. I used minix to<br />develop linux, so I had no access to IO registers, interrupts etc. <br />Under DOS it would have been possible to get access to all these, but<br />then you don't have 32-bit mode. Intel isn't that great - it would<br />probably have been much easier on a 68040 or similar. <br />So after getting a simple task-switcher (it switched between two<br />processes that printed AAAA... and BBBB... respectively by using the<br />timer-interrupt - Gods I was proud over that), I still had to continue<br />debugging basically by using printf. The first thing written was the<br />keyboard driver: that's the reason it's still written completely in<br />assembler (I didn't dare move to C yet - I was still debugging at<br />about instruction-level). <br />After that I wrote the serial drivers, and voila, I had a simple<br />terminal program running (well, not that simple actually). It was still<br />the same two processes (AAA..), but now they read and wrote to the<br />console/serial lines instead. I had to reboot to get out of it all, but<br />it was a simple kernel.<br />After that is was plain sailing: hairy coding still, but I had some<br />devices, and debugging was easier. I started using C at this stage, and<br />it certainly speeds up developement. This is also when I start to get<br />serious about my megalomaniac ideas to make 'a better minix that minix'. <br />I was hoping I'd be able to recompile gcc under linux some day... <br />The harddisk driver was more of the same: this time the problems with<br />bad documentation started to crop up. The PC may be the most used<br />architecture in the world right now, but that doesn't mean the docs are<br />any better: in fact I haven't seen /any/ book even mentioning the weird<br />386-387 coupling in an AT etc (Thanks Bruce). <br />After that, a small filesystem, and voila, you have a minimal unix. Two<br />months for basic setups, but then only slightly longer until I had a<br />disk-driver (seriously buggy, but it happened to work on my machine) and<br />a small filesystem. That was about when I made 0.01 available (late<br />august-91? Something like that): it wasn't pretty, it had no floppy<br />driver, and it couldn't do much anything. I don't think anybody ever<br />compiled that version. But by then I was hooked, and didn't want to<br />stop until I could chuck out minix.<br />>3) Would new linkers and loaders have to be written before you get a basic<br />> kernel running?<br />All versions up to about 0.11 were crosscompiled under minix386 - as<br />were the user programs. I got bash and gcc eventually working under<br />0.02, and while a race-condition in the buffer-cache code prevented me<br />from recompiling gcc with itself, I was able to tackle smaller compiles. <br />0.03 (October?) was able to recompile gcc under itself, and I think<br />that's the first version that anybody else actually used. Still no<br />floppies, but most of the basic things worked.<br />Afetr 0.03 I decided that the next version was actually useable (it was,<br />kind of, but boy is X under 0.96 more impressive), and I called the next<br />version 0.10 (November?). It still had a rather serious bug in the<br />buffer-cache handling code, but after patching that, it was pretty ok. <br />0.11 (December) had the first floppy driver, and was the point where I<br />started doing linux developement under itself. Quite as well, as I<br />trashed my minix386 partition by mistake when trying to autodial<br />/dev/hd2.<br />By that time others were actually using linux, and running out of<br />memory. Especially sad was the fact that gcc wouldn't work on a 2MB<br />machine, and although c386 was ported, it didn't do everything gcc did,<br />and couldn't recompile the kernel. So I had to implement disk-paging:<br />0.12 came out in January (?) and had paging by me as well as job control<br />by tytso (and other patches: pmacdona had started on VC's etc). It was<br />the first release that started to have 'non-essential' features, and<br />being partly written by others. It was also the first release that<br />actually did many things better than minix, and by now people started to<br />really get interested. <br />Then it was 0.95 in March, bugfixes in April, and soon 0.96. It's<br />certainly been fun (and I trust will continue to be so) - reactions have<br />been mostly very positive, and you do learn a lot doing this type of<br />thing (on the other hand, your studies suffer in other respects Linus<br /> <br /> <br /> |
|