Page 1 of 1
Learning by playing around - is this a start?
Posted: Mon Jan 18, 2010 2:41 pm
by Tootles
Hi everyone, I'd just like some opinions on this if anyone would be willing. I want to start out by writing something that looks like an OS but runs in usermode, so I can just learn on a high level how kernels work - at that point the whole thing will be a big lump of executable code. I want to work towards a bootable system once I've learned enough about C and sussing my own libraries out, but a lookalike will do for me right now.
Anyway, if anyone can tell me if this little program I wrote this afternoon is anything like the very first step in my plan should look like, I'd appreciate it. But I'd appreciate it even more if a few nudges into the right direction could be provided!
Code: Select all
/*
* A simple attempt at having a process running alongside another.
* What I'm working towards is a kernel that runs a 'program' (whether
* the 'program' is coded into the same executable or not) and accepts
* interrupts back.
*
* by Mark Tuson, 18 January 2010.
*/
#include <stdio.h>
#include <math.h>
/*
* 'a' - 'i' are like core, that's why they're global.
*/
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
int f = 0;
int g = 0;
int h = 0;
int i = 0;
/*
* 'interrupt' is sort of like an interrupt. It's an array beacuse it makes
* sense that way.
*/
int interrupt [3];
/*
* the jobs.
*/
int job1();
int job2();
int job3();
/*
* Probably the closest thing to a kernel I've ever written, though
* I'm pretty certain it doesn't resemble one in any way at all.
*
* The 'interrupt' that is generally given back is 0, but if it's
* 1, then that job is not done any more; it's aldready finished.
*/
int main() {
for (;;) {
if (interrupt [1] != 1) {
job1(); }
if (interrupt [2] != 1) {
job2(); }
if (interrupt [3] != 1) {
job3(); } }
return 0;}
/*
* A simple job that counts from 10 to 20 and finishes when the result is 20.
*/
int job1() {
if (a == 0) {
a = 1;
b = 10;
c = 1; }
b = (b + c);
printf(" job 1: %d\n",b);
if (b == 20) {
interrupt [1] = 1;
printf("\n\n job 1 finished.\n\n"); }
return interrupt [1]; }
/*
* A simple job that counts down in 10s from 200, to 0. When the results is
* 0, it ends.
*/
int job2() {
if (d == 0) {
d = 2;
e = 200;
f = 10; }
e = (e - f);
printf(" job 2: %d\n",e);
if (e == 0) {
interrupt [2] = 1;
printf("\n\n job 2 finished.\n\n"); }
return interrupt [2]; }
/*
* A simple job that doubles the previous number (starting with 2) until
* the answer is 65536.
*/
int job3() {
if (g == 0) {
g = 1;
h = 2;
i = 2; }
h = (h * i);
printf(" job 3: %d\n",h);
if (h == 65536) {
interrupt [3] = 1;
printf("\n\n job 3 finished.\n\n"); }
return interrupt [3]; }
Thanks very much.
Re: Learning by playing around - is this a start?
Posted: Mon Jan 18, 2010 4:07 pm
by Gigasoft
Well, that's not how operating systems typically run programs. Tasks should not return until they're finished. Instead, tasks are preempted by the OS at regular intervals (when handling a clock interrupt) or paused when the software requests it (for example, to wait on an event). You can't avoid using assembly when implementing task switching. If you're just learning C and haven't started learning assembly yet, you ought to wait until you're proficient in both before starting on anything OS-related.
For an OS prototype running in user mode, you should at least be able to implement cooperative multitasking. This is done almost as you would do when implementing a real OS, but is easier to debug since you can use an existing application level debugger.
Re: Learning by playing around - is this a start?
Posted: Mon Jan 18, 2010 4:59 pm
by Tootles
No, I didn't think it's how it works, but it was my closest effort to being an attempt. Where can I learn about what it takes to do cooperative multitasking?
Re: Learning by playing around - is this a start?
Posted: Mon Jan 18, 2010 5:58 pm
by NickJohnson
Without hardware or native OS support, it's pretty hard to make something that does the sort of multitasking found in an OS. You can use multiple threads, but then its already abstracted away for you. The best you can do in userspace without a virtual machine is something like a library or runtime. Cooperative multitasking could work, but it would require a lot of assembly hacking to get stuff working in C.
Do you learn to swim by running around acting like a fish, or by jumping in the water?
Re: Learning by playing around - is this a start?
Posted: Mon Jan 18, 2010 6:19 pm
by Tootles
NickJohnson wrote:Without hardware or native OS support, it's pretty hard to make something that does the sort of multitasking found in an OS. You can use multiple threads, but then its already abstracted away for you. The best you can do in userspace without a virtual machine is something like a library or runtime. Cooperative multitasking could work, but it would require a lot of assembly hacking to get stuff working in C.
Do you learn to swim by running around acting like a fish, or by jumping in the water?
So the closest thing would be to write my wannabe kernel as a set of functions, and call those functions as though they were any other function in any other program?
Frankly, I couldn't say anything about swimming, because if you put me in water I'll just drown straight away. But where programming's concerned, I seem to learn better when I'm trying to piece a project together, researching and learning as I need to implement a new function.
I suppose I could be QEMU's friend for a while, and make floppy images to boot from. Is that any quicker to do?
Anyway, I'll continue to look around the wiki and see if I can pick anything up - but I'm no good at picking theoretical stuff up without having something to do with it, some way of immediately implementing what I've just learned.
Thanks very much.
Re: Learning by playing around - is this a start?
Posted: Mon Jan 18, 2010 7:31 pm
by nedbrek
NickJohnson wrote:Without hardware or native OS support, it's pretty hard to make something that does the sort of multitasking found in an OS. You can use multiple threads, but then its already abstracted away for you. The best you can do in userspace without a virtual machine is something like a library or runtime. Cooperative multitasking could work, but it would require a lot of assembly hacking to get stuff working in C.
Do you learn to swim by running around acting like a fish, or by jumping in the water?
Hundreds of millions of years ago
, I used a framework called Yacsim. It is oriented towards hardware design, but it does userland stack swapping (using asm modules).
http://softlib.rice.edu/rppt.html
It has a notion of processes (while(1)) and events (one time function calls). You should be able to extract the scheduler and stack-swap code from it. Processes are effectively cooperative multitasking programs (with a shared memory space). You could delete the notion of time, or just always set the elapsed time to 0.
I believe OS students used to use something similar (today, I imagine they just use Bochs or something). I forget what it was called...
Re: Learning by playing around - is this a start?
Posted: Tue Jan 19, 2010 2:18 am
by Grunt
If you're just starting, you could give OSKit a try -
http://www.cs.utah.edu/flux/oskit/. IIRC it supports running an OS inside your own (Linux/Windows). If not, then maybe there's something else that does, and I'm confusing it with OSKit.
Re: Learning by playing around - is this a start?
Posted: Tue Jan 19, 2010 5:41 am
by Kevin
toots wrote:I suppose I could be QEMU's friend for a while, and make floppy images to boot from. Is that any quicker to do?
That's what most people do, and at least it's a lot nearer to reality. By the way, with current qemu versions you don't even need to fiddle around with images for the first steps, but can directly boot multiboot compatible kernels with
qemu -kernel foo.
Re: Learning by playing around - is this a start?
Posted: Tue Jan 19, 2010 7:36 am
by Tootles
So I compile my kernel with cc foo.c? What executable format am I compiling to, and how can I do that? And work through the barebones tutorials?
Where might I find appropriate tutorials to learn how to do the things mentioned at
http://wiki.osdev.org/C#Learning_C?
Re: Learning by playing around - is this a start?
Posted: Tue Jan 19, 2010 2:36 pm
by Synon
Kevin wrote:directly boot multiboot compatible kernels with qemu -kernel foo.
Cool, I didn't know that.
Grunt wrote:If not, then maybe there's something else that does, and I'm confusing it with OSKit.
Damn Small Linux loads itself into memory as an OS running within an OS. Maybe that's what you're thinking of?
http://www.damnsmalllinux.org/ wrote:
1 Boot from a business card CD as a live linux distribution (LiveCD)
2 Boot from a USB pen drive
3 Boot from within a host operating system (that's right, it can run *inside* Windows)
4 Run very nicely from an IDE Compact Flash drive via a method we call "frugal install"
5 Transform into a Debian OS with a traditional hard drive install
6 Run light enough to power a 486DX with 16MB of Ram
7 Run fully in RAM with as little as 128MB (you will be amazed at how fast your computer can be!)
8 Modularly grow -- DSL is highly extendable without the need to customize
3 and 7 specifically.
toots wrote:
http://wiki.osdev.org/Barebones is extremely useful. Personally I'm not going to start for at least a year or so, until I'm sure I'll have enough experience with C and ASM to at least make some headway. I have roughly a years experience with C (and < 6 months with ASM and Python plus < 1 month with Perl), and I think 2 years will be enough just to make something simple.
I am playing around with the code in some tutorials, changing it and learning how it works. Perhaps you could do something similar? Right now I'm writing tools, learning how to write Makefiles, etc. I'm also going to learn how to write linker scripts for ld. One thing I'm writing is an LZSS compressor and an MD5 program. Then I'll either use those to check the integrity of and decompress my kernel either in a bootloader (if I decide I want to write one (I probably will)) or as an intermediate step between the bootloader and kernel (e.g. in the boot.S file that you see in the barebones tutorial; although that would have to be compiled as a separate program so it didn't get compressed too).
Re: Learning by playing around - is this a start?
Posted: Tue Jan 19, 2010 3:49 pm
by Tootles
Yeah, I was specifically referring to the things I'd need to learn according to that page:
* program that writes a string, asks for your name, writes two line breaks and writes another string and the provided name;
* implement strcopy(), strncopy(), strncmp() and other string manipulation functions. What is a buffer overflow?
* implement memmove() or memcpy(). Can you do it with inline assembly so it be faster?
* use inline assembly to perform CPUID and interpret the results;
* use typedefs to name uint32 for a 32-bit unsigned integer type; what type is signed 16-bit?
* use structs and pointers to implement a singly linked lists.
* divide the program with singly linked lists to main.c, list.c and list.h. What is a header guard?
* learn about inline, static, volatile; ternary operator; casts;
* use C preprocessor to write MAX, MIN macros; to print out the current function name, line number;
* use C preprocessor to write a log function which takes a level for the first argument, and uses printf() on the rest of the arguments if the level is higher or equal to current logging threshold.
Of course, I'd hope I'd pick other stuff up as well. As it is, I'm just learning C (I'm in transit from C++, which makes easier work of handling strings and the like). In fact, probably all I can do on that list is (divide the program with singly linked lists to main.c, list.c and list.h. What is a header guard?) So I'm asking if there are any really good tutorials around on the Internet that start from basics - if that's what I need to do, then that's what I'll do.
Re: Learning by playing around - is this a start?
Posted: Wed Jan 20, 2010 2:15 pm
by Synon
toots wrote:Yeah, I was specifically referring to the things I'd need to learn according to that page:
* program that writes a string, asks for your name, writes two line breaks and writes another string and the provided name;
* implement strcopy(), strncopy(), strncmp() and other string manipulation functions. What is a buffer overflow?
* implement memmove() or memcpy(). Can you do it with inline assembly so it be faster?
* use inline assembly to perform CPUID and interpret the results;
* use typedefs to name uint32 for a 32-bit unsigned integer type; what type is signed 16-bit?
* use structs and pointers to implement a singly linked lists.
* divide the program with singly linked lists to main.c, list.c and list.h. What is a header guard?
* learn about inline, static, volatile; ternary operator; casts;
* use C preprocessor to write MAX, MIN macros; to print out the current function name, line number;
* use C preprocessor to write a log function which takes a level for the first argument, and uses printf() on the rest of the arguments if the level is higher or equal to current logging threshold.
Of course, I'd hope I'd pick other stuff up as well. As it is, I'm just learning C (I'm in transit from C++, which makes easier work of handling strings and the like). In fact, probably all I can do on that list is (divide the program with singly linked lists to main.c, list.c and list.h. What is a header guard?) So I'm asking if there are any really good tutorials around on the Internet that start from basics - if that's what I need to do, then that's what I'll do.
Try the tutorial here:
CProgramming.com, specifically
http://www.cprogramming.com/tutorial.html#ctutorial.
Re: Learning by playing around - is this a start?
Posted: Thu Jan 21, 2010 12:57 pm
by Tootles
Thanks. I'll have a go at that.