操作系统内核知识汇总英文版文档格式.docx
《操作系统内核知识汇总英文版文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统内核知识汇总英文版文档格式.docx(36页珍藏版)》请在冰豆网上搜索。
![操作系统内核知识汇总英文版文档格式.docx](https://file1.bdocx.com/fileroot1/2023-2/4/1e8dd4ed-cf57-45ff-ab30-a38644837079/1e8dd4ed-cf57-45ff-ab30-a386448370791.gif)
evenifyoumisssomedetailsyoucangetthegistofwhat’shappening.Themainobstacleisthelackofcontextaroundsomeofthecode,suchaswhenorwhyitrunsortheunderlyingfeaturesofthemachine.Ihopetoprovideabitofthatcontext.Duetobrevity(hah!
)alotoffunstuff–likeinterruptsandmemory–getsonlyanodfornow.ThepostendswiththehighlightsfortheWindowsboot.
AtthispointintheIntelx86bootstorytheprocessorisrunninginreal-mode,isabletoaddress1MBofmemory,andRAMlookslikethisforamodernLinuxsystem:
RAMcontentsafterbootloaderisdone
ThekernelimagehasbeenloadedtomemorybythebootloaderusingtheBIOSdiskI/Oservices.Thisimageisanexactcopyofthefileinyourharddrivethatcontainsthekernel,e.g./boot/vmlinuz-2.6.22-14-server.Theimageissplitintotwopieces:
asmallpartcontainingthereal-modekernelcodeisloadedbelowthe640Kbarrier;
thebulkofthekernel,whichrunsinprotectedmode,isloadedafterthefirstmegabyteofmemory.
Theactionstartsinthereal-modekernelheaderpicturedabove.Thisregionofmemoryisusedtoimplementthe
Linuxbootprotocol
betweenthebootloaderandthekernel.Someofthevaluestherearereadbythebootloaderwhiledoingitswork.Theseincludeamenitiessuchasahuman-readablestringcontainingthekernelversion,butalsocrucialinformationlikethesizeofthereal-modekernelpiece.Thebootloaderalso
writes
valuestothisregion,suchasthememoryaddressforthecommand-lineparametersgivenbytheuserinthebootmenu.Oncethebootloaderisfinishedithasfilledinalloftheparametersrequiredbythekernelheader.It’sthentimetojumpintothekernelentrypoint.Thediagrambelowshowsthecodesequenceforthekernelinitialization,alongwithsourcedirectories,files,andlinenumbers:
Architecture-specificLinuxKernelInitialization
Theearlykernelstart-upfortheIntelarchitectureisinfile
arch/x86/boot/header.S.It’sinassemblylanguage,whichisrareforthekernelatlargebutcommonforbootcode.Thestartofthisfileactuallycontainsbootsectorcode,aleftoverfromthedayswhenLinuxcouldworkwithoutabootloader.Nowadaysthisbootsector,ifexecuted,onlyprintsa“bugger_off_msg”totheuserandreboots.Modernbootloadersignorethislegacycode.Afterthebootsectorcodewehavethefirst15bytesofthereal-modekernelheader;
thesetwopiecestogetheraddupto512bytes,thesizeofatypicaldisksectoronIntelhardware.
Afterthese512bytes,atoffset0×
200,wefindtheveryfirstinstructionthatrunsaspartoftheLinuxkernel:
thereal-modeentrypoint.It’sin
header.S:
110
anditisa2-bytejumpwrittendirectlyinmachinecodeas0x3aeb.Youcanverifythisbyrunninghexdumponyourkernelimageandseeingthebytesatthatoffset–justasanitychecktomakesureit’snotalladream.Thebootloaderjumpsintothislocationwhenitisfinished,whichinturnjumpsto
229
wherewehavearegularassemblyroutinecalledstart_of_setup.Thisshortroutinesetsupastack,zeroesthe
bss
segment(theareathatcontainsstaticvariables,sotheystartwithzerovalues)forthereal-modekernelandthenjumpstogoodoldCcodeat
arch/x86/boot/main.c:
122.
main()doessomehousekeepinglikedetectingmemorylayout,settingavideomode,etc.Itthencalls
go_to_protected_mode().BeforetheCPUcanbesettoprotectedmode,however,afewtasksmustbedone.Therearetwomainissues:
interruptsandmemory.Inreal-modethe
interruptvectortable
fortheprocessorisalwaysatmemoryaddress0,whereasinprotectedmodethelocationoftheinterruptvectortableisstoredinaCPUregistercalledIDTR.Meanwhile,thetranslationoflogicalmemoryaddresses(theonesprogramsmanipulate)tolinearmemoryaddresses(arawnumberfrom0tothetopofthememory)isdifferentbetweenreal-modeandprotectedmode.ProtectedmoderequiresaregistercalledGDTRtobeloadedwiththeaddressofa
GlobalDescriptorTable
formemory.Sogo_to_protected_mode()calls
setup_idt()
and
setup_gdt()
toinstallatemporaryinterruptdescriptortableandglobaldescriptortable.
We’renowreadyfortheplungeintoprotectedmode,whichisdoneby
protected_mode_jump,anotherassemblyroutine.ThisroutineenablesprotectedmodebysettingthePEbitintheCR0CPUregister.Atthispointwe’rerunningwith
paging
disabled;
pagingisanoptionalfeatureoftheprocessor,eveninprotectedmode,andthere’snoneedforityet.What’simportantisthatwe’renolongerconfinedtothe640Kbarrierandcannowaddressupto4GBofRAM.Theroutinethencallsthe32-bitkernelentrypoint,whichis
startup_32
forcompressedkernels.Thisroutinedoessomebasicregisterinitializationsandcalls
decompress_kernel(),aCfunctiontodotheactualdecompression.
decompress_kernel()printsthefamiliar“DecompressingLinux…”message.Decompressionhappensin-placeandonceit’sfinishedtheuncompressedkernelimagehasoverwrittenthecompressedonepicturedinthefirstdiagram.Hencetheuncompressedcontentsalsostartat1MB.decompress_kernel()thenprints“done.”andthecomforting“Bootingthekernel.”By“Booting”itmeansajumptothefinalentrypointinthiswholestory,giventoLinusbyGodhimselfatop
MountainHalti,whichistheprotected-modekernelentrypointatthestartofthesecondmegabyteofRAM(0×
100000).Thatsacredlocationcontainsaroutinecalled,uh,
startup_32.But
this
oneisinadifferentdirectory,yousee.
Thesecondincarnationofstartup_32isalsoanassemblyroutine,butitcontains32-bitmodeinitializations.Itclearsthebsssegmentfortheprotected-modekernel(whichisthe
true
kernelthatwillnowrununtilthemachinerebootsorshutsdown),setsupthefinalglobaldescriptortableformemory,buildspagetablessothatpagingcanbeturnedon,enablespaging,initializesastack,createsthefinalinterruptdescriptortable,andfinallyjumpstotothearchitecture-independentkernelstart-up,
start_kernel().Thediagrambelowshowsthecodeflowforthelastlegoftheboot:
Architecture-independentLinuxKernelInitialization
start_kernel()looksmoreliketypicalkernelcode,whichisnearlyallCandmachineindependent.Thefunctionisalonglistofcallstoinitializationsofthevariouskernelsubsystemsanddatastructures.Theseincludethescheduler,memoryzones,timekeeping,andsoon.start_kernel()thencallsrest_init(),atwhichpointthingsarealmostallworking.rest_init()createsakernelthreadpassinganotherfunction,
kernel_init(),astheentrypoint.rest_init()thencalls
schedule()
tokickstarttaskschedulingandgoestosleepbycalling
cpu_idle(),whichistheidlethreadfortheLinuxkernel.cpu_idle()runsforeverandsodoesprocesszero,whichhostsit.Wheneverthereisworktodo–arunnableprocess–processzerogetsbootedoutoftheCPU,onlytoreturnwhennorunnableprocessesareavailable.
Buthere’sthekickerforus.Thisidleloopistheendofthelongthreadwefollowedsinceboot,it’sthefinaldescendentoftheveryfirst
jump
executedbytheprocessorafterpowerup.Allofthismess,fromresetvectortoBIOStoMBRtobootloadertoreal-modekerneltoprotected-modekernel,allofitleadsrighthere,jumpbyjumpbyjumpitendsintheidleloopforthebootprocessor,cpu_idle().Whichisreallykindofcool.However,thiscan’tbethewholestoryotherwisethecomputerwoulddonowork.
Atthispoint,thekernelthreadstartedpreviouslyisreadytokickin,displacingprocess0anditsidlethread.Andsoitdoes,atwhichpointkernel_init()startsrunningsinceitwasgivenasthethreadentrypoint.
kernel_init()
isresponsibleforinitializingtheremainingCPUsinthesystem,whichhavebeenhaltedsinceboot.Allofthecodewe’veseensofarhasbeenexecutedinasingleCPU,calledthebootprocessor.AstheotherCPUs,calledapplicationprocessors,arestartedtheycomeupinreal-modeandmustrunthroughseveralinitializationsaswell.Manyofthecodepathsarecommon,asyoucanseeinthecodefor
startup_32,butthereareslightforkstakenbythelate-comingapplicationprocessors.Finally,kernel_init()calls
init_post(),whichtriestoexecuteauser-modeprocessinthefollowingorder:
/sbin/init,/etc/init,/bin/init,and/bin/sh.Ifallfail,thekernelwillpanic.Luckilyinitisusuallythere,andstartsrunningasPID1.Itchecksitsconfigurationfiletofigureoutwhichprocessestolaunch,whichmightincludeX11Windows,programsforlogginginontheconsole,networkdaemons,andsoon.ThusendsthebootprocessasyetanotherLinuxboxstartsrunningsomewhere.Mayyouruptimebelonganduntroubled.
TheprocessforWindowsissimilarinmanyways,giventhecommonarchitecture.Manyofthesameproblemsarefacedandsimilarinitializationsmustbedone.WhenitcomestobootoneofthebiggestdifferencesisthatWindowspacksallofthereal-modekernelcode,andsomeoftheinitialprotectedmodecode,intothebootloaderitself(C:
\NTLDR).Soinsteadofhavingtworegionsinthesamekernelimage,Windowsusesdifferentbinaryimages.PlusLinuxcompletelyseparatesbootloaderandkernel;
inawaythisautomatic