linux内核是否有main函数

本篇内容主要讲解“linux内核是否有main函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux内核是否有main函数”吧!

linux内核有main函数;main函数是程序的入口,main是应用程序和操作系统之间约定好的一个接口名,所以linux中每个应用程序的第一个函数必须是main。

linux内核源码之main函数解析

这几天一直在纠结:

main函数是程序的入口,一个程序启动后,经过bootloader的初始化就该经main函数进入C语言的世界,但是linux中每个应用程序的开始都是从main函数开始的。linux下有多个应用程序,岂不是有很多个main。那bootloader会知道跳到哪个main?多个main编译怎么不冲突?

在网上搜索了很久,渐渐的有些明白了:

1、main函数是C语言的入口,这句话没错;但是这句话仅仅是一个约定,而非一个亘古不变的铁律!从程序的更为本质的汇编代码来看,只是大家约定汇编初始化完了后,跳到一个名字叫"main"的标号处;言外之意就是这个标号也是可以改名的,比如linux的C语言入口就是start_kernel();从这个标号地址后就是C语言的天下了。用main这个名字仅仅是因为大家的约定而已,不遵守约定能玩的转也行啊,就像苹果充电线啥的都和别人不一样。

2、在编译时是不存多个main函数的!每个应用程序虽说都有一个main函数(从应用程序来看应用程序的入口是main函数哦);但是应用程序都是独立编译的,不会一起编译,操作系统内核就更不可能和应用程序一起编译了!所以根本不存在多个main冲突的!!可能是统一操作系统与应用程序之间的接口,亦或是侧面影响下main是程序入口的说法,main是应用程序和操作系统之间约定好的一个接口名!所以linux中每个应用程序的第一个函数必须是main。除非你改掉了内核调度的接口地方。

3、linux的应用程序的安装启动也可以类比下我们每天都在用的Windows。Windows应用程序的安装其实也是把一些执行文件拷贝到指定的文件夹里(从绿色软件看),点击就可以运行。linux下也是这样。编译好的bin文件放到指定的文件夹目录下,然后用命令启动执行。

<pre>/*  *  linux/init/main.c  *  *  Copyright (C) 1991, 1992  Linus Torvalds  *  *  GK 2/5/95  -  Changed to support mounting root fs via NFS  *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96  *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96  *  Simplified starting of init:  Michael A. Griffith    * start_kernel->rest_init->kernel_init创建用户init  pid=1                           ->kthreadd管理内核线程     pid=x                           ->pid=0,是idle线程     在rest_init中,会创建kernel_init线程,它负责创建用户init进程,完成工作后,自己     化身为idle线程  */   #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include    #include  #include  #include  #include  #include    #ifdef CONFIG_X86_LOCAL_APIC #include  #endif   static int kernel_init(void *);   extern void init_IRQ(void); extern void fork_init(unsigned long); extern void mca_init(void); extern void sbus_init(void); extern void prio_tree_init(void); extern void radix_tree_init(void); #ifndef CONFIG_DEBUG_RODATA static inline void mark_rodata_ro(void) { } #endif   #ifdef CONFIG_TC extern void tc_init(void); #endif   /*  * Debug helper: via this flag we know that we are in 'early bootup code'  * where only the boot processor is running with IRQ disabled.  This means  * two things - IRQ must not be enabled before the flag is cleared and some  * operations which are not allowed with IRQ disabled are allowed while the  * flag is set.  */ bool early_boot_irqs_disabled __read_mostly;   enum system_states system_state __read_mostly; EXPORT_SYMBOL(system_state);   /*  * Boot command-line arguments  */ #define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT #define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT   extern void time_init(void); /* Default late time init is NULL. archs can override this later. */ void (*__initdata late_time_init)(void); extern void softirq_init(void);   /* Untouched command line saved by arch-specific code. */ char __initdata boot_command_line[COMMAND_LINE_SIZE]; /* Untouched saved command line (eg. for /proc) */ char *saved_command_line; /* Command line for parameter parsing */ static char *static_command_line;   static char *execute_command; static char *ramdisk_execute_command;   /*  * If set, this is an indication to the drivers that reset the underlying  * device before going ahead with the initialization otherwise driver might  * rely on the BIOS and skip the reset operation.  *  * This is useful if kernel is booting in an unreliable environment.  * For ex. kdump situaiton where previous kernel has crashed, BIOS has been  * skipped and devices will be in unknown state.  */ unsigned int reset_devices; EXPORT_SYMBOL(reset_devices);   static int __init set_reset_devices(char *str) {     reset_devices = 1;     return 1; }   __setup("reset_devices", set_reset_devices);   static const char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; const char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; static const char *panic_later, *panic_param;   extern const struct obs_kernel_param __setup_start[], __setup_end[];   static int __init obsolete_checksetup(char *line) {     const struct obs_kernel_param *p;     int had_early_param = 0;       p = __setup_start;     do {         int n = strlen(p->str);         if (parameqn(line, p->str, n)) {             if (p->early) {                 /* Already done in parse_early_param?                  * (Needs exact match on param part).                  * Keep iterating, as we can have early                  * params and __setups of same names 8( */                 if (line[n] == '\0' || line[n] == '=')                     had_early_param = 1;             } else if (!p->setup_func) {                 printk(KERN_WARNING "Parameter %s is obsolete,"                        " ignored\n", p->str);                 return 1;             } else if (p->setup_func(line + n))                 return 1;         }         p++;     } while (p </pre>