linux内核是否有main函数(linux内核函数有哪些)
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文件放到指定的文件夹目录下,然后用命令启动执行。
/*
*linux/init/main.c
*
*Copyright(C)1991,1992LinusTorvalds
*
*GK2/5/95-ChangedtosupportmountingrootfsviaNFS
*Addedinitrd&
change_root:WernerAlmesberger&
HansLermen,Feb'96
*Moanearlyifgccisold,avoidingboguskernels-PaulGortmaker,May'96
*Simplifiedstartingofinit:MichaelA.Griffithgrif@acm.org>
*start_kernel->
rest_init->
kernel_init创建用户initpid=1
->
kthreadd管理内核线程pid=x
->
pid=0,是idle线程
在rest_init中,会创建kernel_init线程,它负责创建用户init进程,完成工作后,自己
化身为idle线程
*/
#includelinux/types.h>
#includelinux/module.h>
#includelinux/proc_fs.h>
#includelinux/kernel.h>
#includelinux/syscalls.h>
#includelinux/stackprotector.h>
#includelinux/string.h>
#includelinux/ctype.h>
#includelinux/delay.h>
#includelinux/ioport.h>
#includelinux/init.h>
#includelinux/initrd.h>
#includelinux/bootmem.h>
#includelinux/acpi.h>
#includelinux/tty.h>
#includelinux/percpu.h>
#includelinux/kmod.h>
#includelinux/vmalloc.h>
#includelinux/kernel_stat.h>
#includelinux/start_kernel.h>
#includelinux/security.h>
#includelinux/smp.h>
#includelinux/profile.h>
#includelinux/rcupdate.h>
#includelinux/moduleparam.h>
#includelinux/kallsyms.h>
#includelinux/writeback.h>
#includelinux/cpu.h>
#includelinux/cpuset.h>
#includelinux/cgroup.h>
#includelinux/efi.h>
#includelinux/tick.h>
#includelinux/interrupt.h>
#includelinux/taskstats_kern.h>
#includelinux/delayacct.h>
#includelinux/unistd.h>
#includelinux/rmap.h>
#includelinux/mempolicy.h>
#includelinux/key.h>
#includelinux/buffer_head.h>
#includelinux/page_cgroup.h>
#includelinux/debug_locks.h>
#includelinux/debugobjects.h>
#includelinux/lockdep.h>
#includelinux/kmemleak.h>
#includelinux/pid_namespace.h>
#includelinux/device.h>
#includelinux/kthread.h>
#includelinux/sched.h>
#includelinux/signal.h>
#includelinux/idr.h>
#includelinux/kgdb.h>
#includelinux/ftrace.h>
#includelinux/async.h>
#includelinux/kmemcheck.h>
#includelinux/sfi.h>
#includelinux/shmem_fs.h>
#includelinux/slab.h>
#includelinux/perf_event.h>
#includeasm/io.h>
#includeasm/bugs.h>
#includeasm/setup.h>
#includeasm/sections.h>
#includeasm/cacheflush.h>
#ifdefCONFIG_X86_LOCAL_APIC
#includeasm/smp.h>
#endif
staticintkernel_init(void*);
externvoidinit_IRQ(void);
externvoidfork_init(unsignedlong);
externvoidmca_init(void);
externvoidsbus_init(void);
externvoidprio_tree_init(void);
externvoidradix_tree_init(void);
#ifndefCONFIG_DEBUG_RODATA
staticinlinevoidmark_rodata_ro(void){
}
#endif
#ifdefCONFIG_TC
externvoidtc_init(void);
#endif
/*
*Debughelper:viathisflagweknowthatwearein'earlybootupcode'
*whereonlythebootprocessorisrunningwithIRQdisabled.Thismeans
*twothings-IRQmustnotbeenabledbeforetheflagisclearedandsome
*operationswhicharenotallowedwithIRQdisabledareallowedwhilethe
*flagisset.
*/
boolearly_boot_irqs_disabled__read_mostly;
enumsystem_statessystem_state__read_mostly;
EXPORT_SYMBOL(system_state);
/*
*Bootcommand-linearguments
*/
#defineMAX_INIT_ARGSCONFIG_INIT_ENV_ARG_LIMIT
#defineMAX_INIT_ENVSCONFIG_INIT_ENV_ARG_LIMIT
externvoidtime_init(void);
/*DefaultlatetimeinitisNULL.archscanoverridethislater.*/
void(*__initdatalate_time_init)(void);
externvoidsoftirq_init(void);
/*Untouchedcommandlinesavedbyarch-specificcode.*/
char__initdataboot_command_line[COMMAND_LINE_SIZE];
/*Untouchedsavedcommandline(eg.for/proc)*/
char*saved_command_line;
/*Commandlineforparameterparsing*/
staticchar*static_command_line;
staticchar*execute_command;
staticchar*ramdisk_execute_command;
/*
*Ifset,thisisanindicationtothedriversthatresettheunderlying
*devicebeforegoingaheadwiththeinitializationotherwisedrivermight
*relyontheBIOSandskiptheresetoperation.
*
*Thisisusefulifkernelisbootinginanunreliableenvironment.
*Forex.kdumpsituaitonwherepreviouskernelhascrashed,BIOShasbeen
*skippedanddeviceswillbeinunknownstate.
*/
unsignedintreset_devices;
EXPORT_SYMBOL(reset_devices);
staticint__initset_reset_devices(char*str)
{
reset_devices=1;
return1;
}
__setup("reset_devices",set_reset_devices);
staticconstchar*argv_init[MAX_INIT_ARGS+2]={
"init",NULL,}
;
constchar*envp_init[MAX_INIT_ENVS+2]={
"HOME=/","TERM=linux",NULL,}
;
staticconstchar*panic_later,*panic_param;
externconststructobs_kernel_param__setup_start[],__setup_end[];
staticint__initobsolete_checksetup(char*line)
{
conststructobs_kernel_param*p;
inthad_early_param=0;
p=__setup_start;
do{
intn=strlen(p->
str);
if(parameqn(line,p->
str,n)){
if(p->
early){
/*Alreadydoneinparse_early_param?
*(Needsexactmatchonparampart).
*Keepiterating,aswecanhaveearly
*paramsand__setupsofsamenames8(*/
if(line[n]=='\0'||line[n]=='=')
had_early_param=1;
}
elseif(!p->
setup_func){
printk(KERN_WARNING"Parameter%sisobsolete,"
"ignored\n",p->
str);
return1;
}
elseif(p->
setup_func(line+n))
return1;
}
p++;
}
while(p__setup_end);
returnhad_early_param;
}
/*
*Thisshouldbeapprox2Bo*oMipstostart(noteinitialshift),andwill
*stillworkevenifinitiallytoolarge,itwilljusttakeslightlylonger
*/
unsignedlongloops_per_jiffy=(112);
EXPORT_SYMBOL(loops_per_jiffy);
staticint__initdebug_kernel(char*str)
{
console_loglevel=10;
return0;
}
staticint__initquiet_kernel(char*str)
{
console_loglevel=4;
return0;
}
early_param("debug",debug_kernel);
early_param("quiet",quiet_kernel);
staticint__initloglevel(char*str)
{
intnewlevel;
/*
*Onlyupdateloglevelvaluewhenacorrectsettingwaspassed,
*topreventblindcrashes(whenloglevelbeingsetto0)that
*arequitehardtodebug
*/
if(get_option(&
str,&
newlevel)){
console_loglevel=newlevel;
return0;
}
return-EINVAL;
}
early_param("loglevel",loglevel);
/*ChangeNULtermbackto"=",tomake"param"thewholestring.*/
staticint__initrepair_env_string(char*param,char*val)
{
if(val){
/*param=valorparam="val"?*/
if(val==param+strlen(param)+1)
val[-1]='=';
elseif(val==param+strlen(param)+2){
val[-2]='=';
memmove(val-1,val,strlen(val)+1);
val--;
}
else
BUG();
}
return0;
}
/*
*Unknownbootoptionsgethandedtoinit,unlesstheylooklike
*unusedparameters(modprobewillfindthemin/proc/cmdline).
*/
staticint__initunknown_bootoption(char*param,char*val)
{
repair_env_string(param,val);
/*Handleobsolete-styleparameters*/
if(obsolete_checksetup(param))
return0;
/*Unusedmoduleparameter.*/
if(strchr(param,'.')&
&
(!val||strchr(param,'.')val))
return0;
if(panic_later)
return0;
if(val){
/*Environmentoption*/
unsignedinti;
for(i=0;
envp_init[i];
i++){
if(i==MAX_INIT_ENVS){
panic_later="Toomanybootenvvarsat`%s'";
panic_param=param;
}
if(!strncmp(param,envp_init[i],val-param))
break;
}
envp_init[i]=param;
}
else{
/*Commandlineoption*/
unsignedinti;
for(i=0;
argv_init[i];
i++){
if(i==MAX_INIT_ARGS){
panic_later="Toomanybootinitvarsat`%s'";
panic_param=param;
}
}
argv_init[i]=param;
}
return0;
}
staticint__initinit_setup(char*str)
{
unsignedinti;
execute_command=str;
/*
*IncaseLILOisgoingtobootuswithdefaultcommandline,
*itprepends"auto"beforethewholecmdlinewhichmakes
*theshellthinkitshouldexecuteascriptwithsuchname.
*Soweignoreallargumentsentered_before_init=...[MJ]
*/
for(i=1;
iMAX_INIT_ARGS;
i++)
argv_init[i]=NULL;
return1;
}
__setup("init=",init_setup);
staticint__initrdinit_setup(char*str)
{
unsignedinti;
ramdisk_execute_command=str;
/*See"auto"commentininit_setup*/
for(i=1;
iMAX_INIT_ARGS;
i++)
argv_init[i]=NULL;
return1;
}
__setup("rdinit=",rdinit_setup);
#ifndefCONFIG_SMP
staticconstunsignedintsetup_max_cpus=NR_CPUS;
#ifdefCONFIG_X86_LOCAL_APIC
staticvoid__initsmp_init(void)
{
APIC_init_uniprocessor();
}
#else
#definesmp_init()do{
}
while(0)
#endif
staticinlinevoidsetup_nr_cpu_ids(void){
}
staticinlinevoidsmp_prepare_cpus(unsignedintmaxcpus){
}
#endif
/*
*Weneedtostoretheuntouchedcommandlineforfuturereference.
*Wealsoneedtostorethetouchedcommandlinesincetheparameter
*parsingisperformedinplace,andweshouldallowacomponentto
*storereferenceofname/valueforfuturereference.
*/
staticvoid__initsetup_command_line(char*command_line)
{
saved_command_line=alloc_bootmem(strlen(boot_command_line)+1);
static_command_line=alloc_bootmem(strlen(command_line)+1);
strcpy(saved_command_line,boot_command_line);
strcpy(static_command_line,command_line);
}
/*
*Weneedtofinalizeinanon-__initfunctionorelseraceconditions
*betweentherootthreadandtheinitthreadmaycausestart_kernelto
*bereapedbyfree_initmembeforetherootthreadhasproceededto
*cpu_idle.
*
*gcc-3.4accidentallyinlinesthisfunction,sousenoinline.
*/
static__initdataDECLARE_COMPLETION(kthreadd_done);
staticnoinlinevoid__init_refokrest_init(void)
{
intpid;
rcu_scheduler_starting();
//READ-COPYUPDATE启动
/*
*Weneedtospawninitfirstsothatitobtainspid1,however
*theinittaskwillendupwantingtocreatekthreads,which,if
*wescheduleitbeforewecreatekthreadd,willOOPS.
*创建一个内核线程,它的线程函数是kernel_init,pid=1,内核进程
*/
kernel_thread(kernel_init,NULL,CLONE_FS|CLONE_SIGHAND);
//numa策略设置
numa_default_policy();
//全局链表kthread_create_list中的kthread内核线程都被运行
//kthreadd线程管理和调度其它内核线程
pid=kernel_thread(kthreadd,NULL,CLONE_FS|CLONE_FILES);
rcu_read_lock();
//通过pid,ini_pid_ns取得kthreadd地址
kthreadd_task=find_task_by_pid_ns(pid,&
init_pid_ns);
rcu_read_unlock();
//通知在kthreadd_done条件的kernel_init线程
complete(&
kthreadd_done);
/*
*Thebootidlethreadmustexecuteschedule()
*atleastoncetogetthingsmoving:
*idle线程初始化
*/
init_idle_bootup_task(current);
//抢占禁用
schedule_preempt_disabled();
/*Callintocpu_idlewithpreemptdisabled*/
cpu_idle();
}
/*Checkforearlyparams.*/
staticint__initdo_early_param(char*param,char*val)
{
conststructobs_kernel_param*p;
for(p=__setup_start;
p__setup_end;
p++){
if((p->
early&
&
parameq(param,p->
str))||
(strcmp(param,"console")==0&
&
strcmp(p->
str,"earlycon")==0)
){
if(p->
setup_func(val)!=0)
printk(KERN_WARNING
"Malformedearlyoption'%s'\n",param);
}
}
/*Weaccepteverythingatthisstage.*/
return0;
}
void__initparse_early_options(char*cmdline)
{
parse_args("earlyoptions",cmdline,NULL,0,0,0,do_early_param);
}
/*Archcodecallsthisearlyon,orifnot,justbeforeotherparsing.*/
void__initparse_early_param(void)
{
static__initdataintdone=0;
static__initdatachartmp_cmdline[COMMAND_LINE_SIZE];
if(done)
return;
/*Allfallthroughtodo_early_param.*/
strlcpy(tmp_cmdline,boot_command_line,COMMAND_LINE_SIZE);
parse_early_options(tmp_cmdline);
done=1;
}
/*
*Activatethefirstprocessor.
*/
staticvoid__initboot_cpu_init(void)
{
intcpu=smp_processor_id();
/*Markthebootcpu"present","online"etcforSMPandUPcase*/
set_cpu_online(cpu,true);
set_cpu_active(cpu,true);
set_cpu_present(cpu,true);
set_cpu_possible(cpu,true);
}
void__init__weaksmp_setup_processor_id(void)
{
}
void__init__weakthread_info_cache_init(void)
{
}
/*
*Setupkernelmemoryallocators
*/
staticvoid__initmm_init(void)
{
/*
*page_cgrouprequirescontiguouspages,
*biggerthanMAX_ORDERunlessSPARSEMEM.
*/
page_cgroup_init_flatmem();
mem_init();
kmem_cache_init();
percpu_init_late();
pgtable_cache_init();
vmalloc_init();
}
asmlinkagevoid__initstart_kernel(void)
{
char*command_line;
externconststructkernel_param__start___param[],__stop___param[];
/*
*Needtorunasearlyaspossible,toinitializethe
*lockdephash:
*/
//初始化2个hash表-LockDependencyValidator(内核依赖的关系表)
lockdep_init();
smp_setup_processor_id();
//空函数
debug_objects_early_init();
//初始化内核调试相关
/*
*SetupthetheinitialcanaryASAP:
*/
boot_init_stack_canary();
//栈溢出保护初始化
//控制组初始化-cgroup-资源任务分组管理
cgroup_init_early();
local_irq_disable();
//关中断
early_boot_irqs_disabled=true;
/*
*Interruptsarestilldisabled.Donecessarysetups,then
*enablethem
*/
tick_init();
//时钟初始化
boot_cpu_init();
//启动cpu初始化
page_address_init();
//页面初始化
printk(KERN_NOTICE"%s",linux_banner);
setup_arch(&
command_line);
//架构相关初始化
mm_init_owner(&
init_mm,&
init_task);
//内存管理初始化
mm_init_cpumask(&
init_mm);
//内存管理初始化
setup_command_line(command_line);
//处理命令行(保存2份)
setup_nr_cpu_ids();
//cpuid相关
setup_per_cpu_areas();
//每cpu变量申请空间(包括gdt)
//smp中用来启动的cpu
smp_prepare_boot_cpu();
/*arch-specificboot-cpuhooks*/
//建立系统内存页区链表
build_all_zonelists(NULL);
//内存页相关初始化
page_alloc_init();
printk(KERN_NOTICE"Kernelcommandline:%s\n",boot_command_line);
//命令行boot_command_line
parse_early_param();
//解析参数
parse_args("Bootingkernel",static_command_line,__start___param,
__stop___param-__start___param,
-1,-1,&
unknown_bootoption);
//
jump_label_init();
/*
*Theseuselargebootmemallocationsandmustprecede
*kmem_cache_init()
*内存初始化相关
*/
setup_log_buf(0);
pidhash_init();
vfs_caches_init_early();
sort_main_extable();
trap_init();
mm_init();
/*
*Setuptheschedulerpriorstartinganyinterrupts(suchasthe
*timerinterrupt).Fulltopologysetuphappensatsmp_init()
*time-butmeanwhilewestillhaveafunctioningscheduler.
*调度初始化
*/
sched_init();
/*
*Disablepreemption-earlybootupschedulingisextremely
*fragileuntilwecpu_idle()forthefirsttime.
*抢占禁用
*/
preempt_disable();
if(!irqs_disabled()){
printk(KERN_WARNING"start_kernel():bug:interruptswere"
"enabled*very*early,fixingit\n");
local_irq_disable();
}
idr_init_cache();
//idr
perf_event_init();
//performanceevent
rcu_init();
//read-copy-update机制
radix_tree_init();
//radix树机制
/*initsomelinksbeforeinit_ISA_irqs()*/
early_irq_init();
//中断请求
init_IRQ();
//中断请求
prio_tree_init();
//优先查找树
init_timers();
//时钟
hrtimers_init();
//High-resolutionkerneltimers高精度内核时钟
softirq_init();
//软中断
timekeeping_init();
//时间相关
time_init();
//时间
profile_init();
//分配内核性能统计保存的内存
call_function_init();
//smp中每cpu的call_single_queue初始化
if(!irqs_disabled())
printk(KERN_CRIT"start_kernel():bug:interruptswere"
"enabledearly\n");
early_boot_irqs_disabled=false;
//中断请求开
local_irq_enable();
//本地中断开
kmem_cache_init_late();
//kmem后期初始化
/*
*HACKALERT!Thisisearly.We'reenablingtheconsolebefore
*we'vedonePCIsetupsetc,andconsole_init()mustbeawareof
*this.Butwedowantoutputearly,incasesomethinggoeswrong.
*/
console_init();
//初始化系统控制台结构
if(panic_later)
panic(panic_later,panic_param);
//锁依赖信息
lockdep_info();
/*
*Needtorunthiswhenirqsareenabled,becauseitwants
*toself-test[hard/soft]-irqson/offlockinversionbugs
*too:
*/
locking_selftest();
#ifdefCONFIG_BLK_DEV_INITRD
if(initrd_start&
&
!initrd_below_start_ok&
&
page_to_pfn(virt_to_page((void*)initrd_start))min_low_pfn){
printk(KERN_CRIT"initrdoverwritten(0x%08lx0x%08lx)-"
"disablingit.\n",
page_to_pfn(virt_to_page((void*)initrd_start)),
min_low_pfn);
initrd_start=0;
}
#endif
page_cgroup_init();
//controlgroups初始化
debug_objects_mem_init();
//对象调试
kmemleak_init();
//检测内核内存泄漏的功能
setup_per_cpu_pageset();
//申请并初始化每cpu页set
numa_policy_init();
//numa相关
if(late_time_init)
late_time_init();
//初始化每cpusched_clock_data=ktime_now
sched_clock_init();
calibrate_delay();
//计算cpuMIPS百万条指令/s
pidmap_init();
//pid进程id表初始化
anon_vma_init();
//虚拟地址
#ifdefCONFIG_X86
if(efi_enabled)//efibois
efi_enter_virtual_mode();
#endif
thread_info_cache_init();
//申请thread_info的内存
cred_init();
//credential健在分配
//根据物理内存大小,计算可创建进/线程数量
fork_init(totalram_pages);
proc_caches_init();
//进程内存初始化
buffer_init();
//页高速缓存
key_init();
//红黑树内存,存keys
security_init();
//安全相关
dbg_late_init();
//调试相关
vfs_caches_init(totalram_pages);
//虚拟文件系统初始化
signals_init();
//sigqueue申请内存,信号系统
/*rootfspopulatingmightneedpage-writeback*/
page_writeback_init();
//页回写
#ifdefCONFIG_PROC_FS
proc_root_init();
//proc文件系统初始化
#endif
cgroup_init();
//cgroup相关
cpuset_init();
//cpuset相关
taskstats_init_early();
//进程计数器
delayacct_init();
//进程延时审计
check_bugs();
//系统bug相关测试
//acpi总线
acpi_early_init();
/*beforeLAPICandSMPinit*/
sfi_init_late();
//SimpleFirmwareInterface
//功能追踪初始化,一种调试工具
ftrace_init();
/*Dotherestnon-__init'ed,we'renowalive*/
rest_init();
}
/*Callallconstructorfunctionslinkedintothekernel.*/
staticvoid__initdo_ctors(void)
{
#ifdefCONFIG_CONSTRUCTORS
ctor_fn_t*fn=(ctor_fn_t*)__ctors_start;
for(;
fn(ctor_fn_t*)__ctors_end;
fn++)
(*fn)();
#endif
}
boolinitcall_debug;
core_param(initcall_debug,initcall_debug,bool,0644);
staticcharmsgbuf[64];
staticint__init_or_moduledo_one_initcall_debug(initcall_tfn)
{
ktime_tcalltime,delta,rettime;
unsignedlonglongduration;
intret;
printk(KERN_DEBUG"calling%pF@%i\n",fn,task_pid_nr(current));
calltime=ktime_get();
ret=fn();
rettime=ktime_get();
delta=ktime_sub(rettime,calltime);
duration=(unsignedlonglong)ktime_to_ns(delta)>
>
10;
printk(KERN_DEBUG"initcall%pFreturned%dafter%lldusecs\n",fn,
ret,duration);
returnret;
}
int__init_or_moduledo_one_initcall(initcall_tfn)
{
intcount=preempt_count();
intret;
if(initcall_debug)
ret=do_one_initcall_debug(fn);
else
ret=fn();
msgbuf[0]=0;
if(ret&
&
ret!=-ENODEV&
&
initcall_debug)
sprintf(msgbuf,"errorcode%d",ret);
if(preempt_count()!=count){
strlcat(msgbuf,"preemptionimbalance",sizeof(msgbuf));
preempt_count()=count;
}
if(irqs_disabled()){
strlcat(msgbuf,"disabledinterrupts",sizeof(msgbuf));
local_irq_enable();
}
if(msgbuf[0]){
printk("initcall%pFreturnedwith%s\n",fn,msgbuf);
}
returnret;
}
externinitcall_t__initcall_start[];
externinitcall_t__initcall0_start[];
externinitcall_t__initcall1_start[];
externinitcall_t__initcall2_start[];
externinitcall_t__initcall3_start[];
externinitcall_t__initcall4_start[];
externinitcall_t__initcall5_start[];
externinitcall_t__initcall6_start[];
externinitcall_t__initcall7_start[];
externinitcall_t__initcall_end[];
staticinitcall_t*initcall_levels[]__initdata={
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
__initcall_end,
}
;
staticchar*initcall_level_names[]__initdata={
"earlyparameters",
"coreparameters",
"postcoreparameters",
"archparameters",
"subsysparameters",
"fsparameters",
"deviceparameters",
"lateparameters",
}
;
staticvoid__initdo_initcall_level(intlevel)
{
externconststructkernel_param__start___param[],__stop___param[];
initcall_t*fn;
strcpy(static_command_line,saved_command_line);
parse_args(initcall_level_names[level],
static_command_line,__start___param,
__stop___param-__start___param,
level,level,
repair_env_string);
for(fn=initcall_levels[level];
fninitcall_levels[level+1];
fn++)
do_one_initcall(*fn);
}
staticvoid__initdo_initcalls(void)
{
intlevel;
for(level=0;
levelARRAY_SIZE(initcall_levels)-1;
level++)
do_initcall_level(level);
}
/*
*Ok,themachineisnowinitialized.Noneofthedevices
*havebeentouchedyet,buttheCPUsubsystemisupand
*running,andmemoryandprocessmanagementworks.
*
*Nowwecanfinallystartdoingsomerealwork..
*/
staticvoid__initdo_basic_setup(void)
{
cpuset_init_smp();
//smpcpuset相关
usermodehelper_init();
//khelper单线程工作队列
shmem_init();
//sheme机制
driver_init();
//驱动各子系统
init_irq_proc();
//proc中创建irq目录
do_ctors();
//内核中所有构造函数,介于.ctors段中的函数
usermodehelper_enable();
//所有编译进内核的驱动模块初始化函数
do_initcalls();
}
staticvoid__initdo_pre_smp_initcalls(void)
{
initcall_t*fn;
for(fn=__initcall_start;
fn__initcall0_start;
fn++)
do_one_initcall(*fn);
}
staticvoidrun_init_process(constchar*init_filename)
{
argv_init[0]=init_filename;
kernel_execve(init_filename,argv_init,envp_init);
}
/*Thisisanon__initfunction.Forceittobenoinlineotherwisegcc
*makesitinlinetoinit()anditbecomespartofinit.textsection
*这是个非Init函数,防止gcc让它内联到init(),并成为Init.text段的一部分
*/
staticnoinlineintinit_post(void)
{
/*needtofinishallasync__initcodebeforefreeingthememory
*在释放init内存前,必须完成所有__init代码执行
*/
async_synchronize_full();
free_initmem();
//释放init.*段中的内存
//修改页表,保证只读数据段为只读属性readonly
mark_rodata_ro();
//系统运行状态标志
system_state=SYSTEM_RUNNING;
//numa默认策略
numa_default_policy();
//当前进程不能被杀掉,只为它是init
current->
signal->
flags|=SIGNAL_UNKILLABLE;
//如果ramdisk_execute_command变量指定了init程序,执行它
if(ramdisk_execute_command){
run_init_process(ramdisk_execute_command);
printk(KERN_WARNING"Failedtoexecute%s\n",
ramdisk_execute_command);
}
/*
*Wetryeachoftheseuntilonesucceeds.
*
*TheBourneshellcanbeusedinsteadofinitifweare
*tryingtorecoverareallybrokenmachine.
*又一个程序,看能不能执行,如果不能,则执行下面4个之一
*/
if(execute_command){
run_init_process(execute_command);
printk(KERN_WARNING"Failedtoexecute%s.Attempting"
"defaults...\n",execute_command);
}
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
//两个变量和4个init都不能成功执行,报错
panic("Noinitfound.Trypassinginit=optiontokernel."
"SeeLinuxDocumentation/init.txtforguidance.");
}
staticint__initkernel_init(void*unused)
{
/*
*Waituntilkthreaddisallset-up.等待kthreadd的启动完成
*/
wait_for_completion(&
kthreadd_done);
/*Nowtheschedulerisfullysetupandcandoblockingallocations
*
*/
gfp_allowed_mask=__GFP_BITS_MASK;
/*
*initcanallocatepagesonanynode
*/
set_mems_allowed(node_states[N_HIGH_MEMORY]);
/*
*initcanrunonanycpu.
*/
set_cpus_allowed_ptr(current,cpu_all_mask);
//cad_pid为接收Ctrl-alt-del操作的INT信号的进程ID,设置成了init的pid
//说明init可接受这3个键
cad_pid=task_pid(current);
//smp系统准备、激活所有cpu
smp_prepare_cpus(setup_max_cpus);
do_pre_smp_initcalls();
lockup_detector_init();
smp_init();
sched_init_smp();
//初始化设备驱动、内核模块
do_basic_setup();
/*Openthe/dev/consoleontherootfs,thisshouldneverfail
*打开/dev/console设备
*/
if(sys_open((constchar__user*)"/dev/console",O_RDWR,0)0)
printk(KERN_WARNING"Warning:unabletoopenaninitialconsole.\n");
/*
*复制两次标准输入0,一个是标准输入1,一个是标准错误2
*/
(void)sys_dup(0);
(void)sys_dup(0);
/*
*checkifthereisanearlyuserspaceinit.Ifyes,letitdoall
*thework
*是否有早期用户空间init进程,有的话,让其执行
*/
if(!ramdisk_execute_command)
ramdisk_execute_command="/init";
if(sys_access((constchar__user*)ramdisk_execute_command,0)!=0){
ramdisk_execute_command=NULL;
prepare_namespace();
}
/*
*Ok,wehavecompletedtheinitialbootup,and
*we'reessentiallyupandrunning.Getridofthe
*initmemsegmentsandstarttheuser-modestuff..
*/
//启动用户空间的init进程
init_post();
return0;
}
到此,相信大家对“linux内核是否有main函数”有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: linux内核是否有main函数(linux内核函数有哪些)
本文地址: https://pptw.com/jishu/699.html