I am learning device drivers and Kernel programming. According to Jonathan Corbet's book, there is no main() function in device drivers.

So I two questions:

  • Why don't we need a main() function in device drivers?
  • Does the kernel itself have a main() function?

Can someone explain this to me?

closed as off-topic by Gilles, jasonwryan, slm, Anthon, Michael Mrozek Aug 17 '13 at 20:42

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question has been posted on multiple sites. Cross-posting is strongly discouraged; see the help center and community FAQ for more information." – Michael Mrozek


In user space programs, main() is the entry point to the program that is called by the libc initialization code when the binary is executed. Kernel code does not have the luxury to rely on libc, as libc itself relies on the kernel syscall interface for memory allocation, I/O, process managements etc.

That said, the equivalent of main() in kernel code is start_kernel(), which is called by the bootloader after having loaded the kernel image, decompressed it into memory and setup essential hardware and memory paging. start_kernel() performs the majority of the system setup and eventually spawns the init process.

The entry point to Linux kernel modules is an init function that is registered with the kernel by calling the module_init() macro. The registered module init function is then called by kernel code through the do_initcalls() function during kernel startup.

  • 11
    Thank you for recognizing the real purpose of the main method in C. (It is an all too commonly held misconception that the OS makes a direct call to main, which isn't the case and is even less the case in e.g. C++.) I'd give you another upvote if I could just for that. – a CVn Aug 16 '13 at 8:01
  • 1
    @Thomas... Thanks for this excellent answer.... – someone Aug 16 '13 at 19:30

The kernel does not have a main function. main is a concept of the C language. The kernel is written in C and assembly. The entry code of the kernel is written by assembly.

The boot sequence is organized as follows:

  1. The BIOS usually loads a boot loader from a boot block device. A popular boot loader right now is grub.
  2. Grub loads a kernel image into ram, possible with an initial root device (initrd). Then code at some address is executed.
  3. The kernel image has some kernel modules, for example: filesystem modules, device drivers. The kernel image use the filesystem module to mount the root filesystem. Now the kernel can load and run all kernel modules from disk.
  4. The kernel runs initialization tasks. For example: traverse PCI bus and find all PCI devices, initialize all device drivers.
  5. Finally the kernel creates process 0 and process 1 (the init process), switches the context of CPU from ring 0 to ring 3, and starts the init process (the process id is 1). Now the kernel boot is finished!
  6. The init program runs all init scripts. All services are started. Shell is called. Users can login.

The main function is a C function. Actually main method is not the entry point of C programs. The C runtime calls many functions before main. GCC has a extend feature: constructors. Functions declared "constructor" are called before main.

For example:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \

This macro is from the qemu project.

  • Main method is a c method.Actually main method is not the entry of c program.C runtime has called many methods before main method. – Edward Shen Aug 16 '13 at 6:10
  • well, bios usually loads a boot loader, and that boot loader loads a kernel image (and possibly an initrd). The code of the kernel is in the kernel image, not initrd – Stéphane Chazelas Aug 16 '13 at 6:11
  • GCC has a extend feature: constructor. The method declaration "constructor" is called before main method. For example: /* This should not be used directly. Use block_init etc. instead. */ #define module_init(function, type) \ static void _attribute__((constructor)) do_qemu_init ## function(void) { \ register_module_init(function, type); \ } – Edward Shen Aug 16 '13 at 6:12
  • 1
    initrd.img IS NOT the kernel image. It's a set of modules loaded by the kernel at boot. Kernel images usually have names starting with "vmlinuz" but differ from distro to distro. – goldilocks Aug 16 '13 at 6:52
  • 3
    This answer is chock-full of "everything is a PC/Linux/i86" and it boots that way and the kernel is that way... Why does everybody think that's the only possible way in the world? – Jens Aug 16 '13 at 17:35

There is e.g. a main() function in arch/x86/boot/main.c for preparing the system to switch from the real to the protected mode but other architectures don't have such a code. There is a nice overview how booting of Linux kernel 2.6.x on x86 platform works. It's really worth reading it.

According the document HOWTO do Linux kernel development, the Linux kernel is

a freestanding C environment, with no reliance on the standard C library, so some portions of the C standard are not supported.

what according the C standard BTW means that

It is implementation-defined whether a program in a freestanding environment is required to define a 'main' function.

Not the answer you're looking for? Browse other questions tagged or ask your own question.