In Linux 0.11, we can see there is a main.c with a main()
In my understanding, the object code needs an OS to run it.
I mean, since Linux 0.11 is an OS, who is in front of it to run it? DOS?
The name of
main() was simply chosen for familiarity and esthetical reasons; there was no C runtime calling it, as with the
main() from a user land program. There's even a comment that tells as much in
void main(void) /* This really IS void, no error here. */
main() function is called from
after_page_tables: pushl $0 # These are the parameters to main :-) pushl $0 pushl $0 pushl $L6 # return address for main, if it decides to. pushl $_main jmp setup_paging L6: jmp L6 # main should never return here, but # just in case, we know what happens
Notice how the address of
main is pushed on the stack, and
setup_paging is called with
jmp, not with
call, which means that the
ret at its end will continue from the start of
The Linux kernel, especially in the 0.11 days, was loaded directly by the hardware BIOS.
Basically the BIOS looks at the boot sector (of a floppy) or the Master Boot Record of a hard disk, and loads that sector. With a hard disk the MBR then loads the "primary partition" boot sector.
This loaded boot sector has enough information to know about how to load the kernel into memory, and then run it.
With the old old 0.11 disks it was effectively a floppy boot solution, with the kernel on one disk and root on another disk, so the boot system was very very simple.
When Linux handled hard disks the boot process was still very simple. It was so simple that it became possible to create tools such as "loadlin" which was a simple DOS program that would load the Linux kernel and boot into it, emulating the BIOS loader. In this way a DOS config.sys menu could be created to boot DOS or Linux; an early form of dual booting.
But at it's heart, the Linux kernel is loaded from "bare metal" and takes over the machine.
main function is a feature of the C language. How exactly it gets converted into a computer instruction for the CPU to "start here" is basically a compiler implementation detail. On bare metal, you can often simply rely on the hardware to start execution at a particular memory address when it first boots. Early versions of Linux depended on a. simple x86 boot loader; today, that role is typically handled by Grub. That behavior, in turn, depends on BIOS firmware conventions, But really, at every level, you have a piece of computer architecture with a convention for how to start a program.