En introduktion till Linux uppstarts- och startprocesser

Det är viktigt att förstå Linux uppstarts- och startprocesser för att kunna konfigurera Linux och lösa uppstartsproblem. Den här artikeln ger en översikt över uppstartssekvensen med hjälp av GRUB2 bootloader och uppstartssekvensen som utförs av initialiseringssystemet systemd.

I verkligheten finns det två sekvenser av händelser som krävs för att starta upp en Linuxdator och göra den användbar: uppstart och uppstart. Uppstartssekvensen börjar när datorn slås på och avslutas när kärnan initieras och systemd startas. Uppstartsprocessen tar sedan över och avslutar uppgiften att få Linuxdatorn i ett funktionsdugligt tillstånd.

Samt sett är uppstarts- och startprocessen för Linux ganska enkel att förstå. Den består av följande steg som kommer att beskrivas mer i detalj i följande avsnitt.

  • BIOS POST
  • Boot loader (GRUB2)
  • Kernelinitialisering
  • Start av systemd, överordnad till alla processer.

Bemärk att den här artikeln täcker GRUB2 och systemd eftersom de är de aktuella boot loader- och initialiseringsprogrammen för de flesta större distributioner. Andra programvarualternativ har använts historiskt och finns fortfarande i vissa distributioner.

Startprocessen

Startprocessen kan initieras på ett av flera sätt. För det första, om strömmen är avstängd, startar uppstartsprocessen genom att slå på strömmen. Om datorn redan kör en lokal användare, inklusive root eller en icke-priviligierad användare, kan användaren programmatiskt initiera startsekvensen genom att använda GUI eller kommandoraden för att initiera en omstart. En omstart gör först en avstängning och startar sedan om datorn.

BIOS POST

Det första steget i Linux uppstartsprocess har egentligen ingenting med Linux att göra. Detta är hårdvarudelen av uppstartsprocessen och är detsamma för alla operativsystem. När datorn först sätts på strömmen körs POST (Power On Self Test) som är en del av BIOS (Basic I/O System).

När IBM utformade den första PC:n 1981, utformades BIOS för att initialisera hårdvarukomponenterna. POST är den del av BIOS vars uppgift är att se till att datorhårdvaran fungerar korrekt. Om POST misslyckas kan det hända att datorn inte går att använda och därför fortsätter inte uppstartsprocessen.

BIOS POST kontrollerar maskinvarans grundläggande funktionsduglighet och utfärdar sedan ett BIOS-avbrott, INT 13H, som lokaliserar uppstartssektorerna på eventuella anslutna uppstartsbara enheter. Den första uppstartssektorn den hittar som innehåller en giltig uppstartspost laddas in i RAM och kontrollen överförs sedan till den kod som laddades från uppstartssektorn.

Uppstartssektorn är egentligen det första steget i uppstartsladdaren. Det finns tre startladdare som används av de flesta Linuxdistributioner, GRUB, GRUB2 och LILO. GRUB2 är den senaste och används numera mycket oftare än de andra äldre alternativen.

GRUB2

GRUB2 står för ”GRand Unified Bootloader, version 2” och är numera den primära starthanteraren för de flesta aktuella Linuxdistributioner. GRUB2 är programmet som gör datorn precis tillräckligt smart för att hitta operativsystemets kärna och ladda in den i minnet. Eftersom det är lättare att skriva och säga GRUB än GRUB2 kan det hända att jag använder termen GRUB i det här dokumentet, men jag kommer att hänvisa till GRUB2 om inget annat anges.

GRUB har utformats för att vara kompatibel med multibootspecifikationen, vilket gör det möjligt för GRUB att starta upp många versioner av Linux och andra fria operativsystem; det kan också kedjeladda uppstartsregistret för proprietära operativsystem.

GRUB kan också tillåta användaren att välja att starta upp från flera olika kärnor för en given Linuxdistribution. Detta ger möjlighet att starta upp till en tidigare kärnversion om en uppdaterad kärna på något sätt misslyckas eller är inkompatibel med en viktig programvara. GRUB kan konfigureras med hjälp av filen /boot/grub/grub.conf.

GRUB1 anses nu vara gammal och har i de flesta moderna distributioner ersatts av GRUB2, som är en omskrivning av GRUB1. Red Hat-baserade distributioner uppgraderades till GRUB2 runt Fedora 15 och CentOS/RHEL 7. GRUB2 ger samma uppstartsfunktionalitet som GRUB1, men GRUB2 är också en mainframe-liknande kommandobaserad pre-OS-miljö och ger större flexibilitet under pre-boot-fasen. GRUB2 konfigureras med /boot/grub2/grub.cfg.

Den primära funktionen för endera GRUB är att få Linuxkärnan inläst i minnet och igång. Båda versionerna av GRUB fungerar i princip på samma sätt och har samma tre steg, men jag kommer att använda GRUB2 för den här diskussionen om hur GRUB gör sitt jobb. Konfigurationen av GRUB eller GRUB2 och användningen av GRUB2-kommandon ligger utanför den här artikelns räckvidd.

Och även om GRUB2 inte officiellt använder sig av stage-notationen för de tre stegen i GRUB2 är det bekvämt att hänvisa till dem på det sättet, så det kommer jag att göra i den här artikeln.

Steg 1

Som nämnts i avsnittet om BIOS POST söker BIOS i slutet av POST på de anslutna diskarna efter en uppstartspost, som vanligtvis finns i Master Boot Record (MBR), den laddar in den första den hittar i minnet och startar sedan utförandet av uppstartsposten. Uppstartskoden, dvs. GRUB2 stage 1, är mycket liten eftersom den måste rymmas i den första 512-byte sektorn på hårddisken tillsammans med partitionstabellen. Det totala utrymmet för själva bootstrap-koden i en klassisk generisk MBR är 446 byte. Den 446 byte stora filen för steg 1 heter boot.img och innehåller inte partitionstabellen, som läggs till separat i boot record.

Då boot record måste vara så liten är den inte heller särskilt smart och förstår inte filsystemstrukturer. Därför är det enda syftet med steg 1 att lokalisera och ladda steg 1.5. För att åstadkomma detta måste steg 1.5 i GRUB placeras i utrymmet mellan själva startregistret och den första partitionen på enheten. Efter att ha laddat GRUB steg 1.5 i RAM överlåter steg 1 kontrollen till steg 1.5.

Steg 1.5

Som nämnts ovan måste steg 1.5 i GRUB finnas i utrymmet mellan själva startregistret och den första partitionen på hårddisken. Detta utrymme lämnades historiskt sett oanvänt av tekniska skäl. Den första partitionen på hårddisken börjar vid sektor 63 och med MBR i sektor 0 återstår 62 512-byte-sektorer – 31 744 byte – för att lagra filen core.img som är steg 1.5 i GRUB. Core.img-filen är 25 389 byte så det finns gott om utrymme mellan MBR och den första skivpartitionen för att lagra den.

På grund av den större mängden kod som kan rymmas i steg 1.5 kan den ha tillräckligt med kod för att innehålla några vanliga filsystemsdrivrutiner, t.ex. standard EXT och andra Linux-filsystem, FAT och NTFS. GRUB2 core.img är mycket mer komplex och kapabel än den äldre GRUB1 stage 1.5. Detta innebär att steg 2 av GRUB2 kan placeras på ett standard EXT-filsystem, men det kan inte placeras på en logisk volym. Så standardplaceringen för steg 2-filerna är i filsystemet /boot, närmare bestämt /boot/grub2.

Bemärk att katalogen /boot måste ligga på ett filsystem som stöds av GRUB. Det är inte alla filsystem som är det. Funktionen för steg 1.5 är att påbörja utförandet med de filsystemdrivrutiner som är nödvändiga för att hitta filerna för steg 2 i filsystemet /boot och ladda de nödvändiga drivrutinerna.

Steg 2

Alla filer för GRUB steg 2 finns i katalogen /boot/grub2 och flera underkataloger. GRUB2 har ingen avbildningsfil som steg 1 och 2. Istället består den mestadels av körtidskärnmoduler som laddas vid behov från katalogen /boot/grub2/i386-pc.

Funktionen för GRUB2 steg 2 är att lokalisera och ladda en Linuxkärna i RAM och överlämna kontrollen över datorn till kärnan. Kärnan och dess tillhörande filer finns i katalogen /boot. Kärnans filer är identifierbara eftersom de alla har ett namn som börjar med vmlinuz. Du kan lista innehållet i /boot-katalogen för att se vilka kärnor som för närvarande är installerade på ditt system.

GRUB2, liksom GRUB1, stöder uppstart från en av ett urval av Linuxkärnor. Red Hat-pakethanteraren, DNF, stöder att flera versioner av kärnan sparas så att en äldre version av kärnan kan startas upp om ett problem uppstår med den nyaste versionen. Som standard tillhandahåller GRUB en pre-boot-meny med de installerade kärnorna, inklusive ett räddningsalternativ och, om det är konfigurerat, ett återställningsalternativ.

Steg 2 av GRUB2 laddar den valda kärnan i minnet och överlåter kontrollen över datorn till kärnan.

Kärnan

Alla kärnor är i ett komprimerat format som är självutlämnande för att spara utrymme. Kärnorna finns i katalogen /boot, tillsammans med en inledande RAM-diskavbildning och enhetskartor för hårddiskarna.

När den valda kärnan har laddats in i minnet och börjar exekveras, måste den först extrahera sig själv från den komprimerade versionen av filen innan den kan utföra något användbart arbete. När kärnan har extraherat sig själv laddar den systemd, som är ersättaren för det gamla initprogrammet SysV, och överlämnar kontrollen till det.

Detta är slutet på uppstartsprocessen. Vid denna tidpunkt körs Linuxkärnan och systemd men kan inte utföra några produktiva uppgifter för slutanvändaren eftersom inget annat körs.

Startprocessen

Startprocessen följer uppstartsprocessen och för Linuxdatorn upp till ett operativt tillstånd där den är användbar för produktivt arbete.

systemd

Systemd är alla processers moder och är ansvarig för att föra Linuxvärden upp till ett tillstånd där produktivt arbete kan utföras. Några av dess funktioner, som är mycket mer omfattande än det gamla init-programmet, är att hantera många aspekter av en fungerande Linuxvärddator, inklusive montering av filsystem samt att starta och hantera de systemtjänster som krävs för att ha en produktiv Linuxvärddator. Alla av systemd:s uppgifter som inte är relaterade till startsekvensen ligger utanför den här artikelns räckvidd.

Först monterar systemd filsystemen enligt definitionen i /etc/fstab, inklusive eventuella swapfiler eller partitioner. Vid det här laget har den tillgång till de konfigurationsfiler som finns i /etc, inklusive sina egna. Den använder sin konfigurationsfil, /etc/systemd/system/default.target, för att bestämma i vilket tillstånd eller mål den ska starta upp värden. Filen default.target är endast en symbolisk länk till den verkliga målfilen. För en stationär arbetsstation är detta vanligtvis graphical.target, vilket motsvarar runlevel 5 i det gamla SystemV init. För en server är det troligare att standardfilen är multi-user.target som motsvarar runlevel 3 i SystemV. Emergency.target liknar single user mode.

Bemärk att mål och tjänster är systemd-enheter.

Tabell 1 nedan är en jämförelse mellan systemd-målen och de gamla körnivåerna i SystemV-start. Systemd-målaliaserna tillhandahålls av systemd för bakåtkompatibilitet. Målaliaserna gör det möjligt för skript – och för många sysadmins som jag själv – att använda SystemV-kommandon som init 3 för att ändra runlevels. Of course, the SystemV commands are forwarded to systemd for interpretation and execution.

SystemV Runlevel systemd target systemd target aliases Description
halt.target Halts the system without powering it down.
0 poweroff.target runlevel0.target Halts the system and turns the power off.
S emergency.target Single user mode. No services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system.
1 rescue.target runlevel1.target A base system including mounting the filesystems with only the most basic services running and a rescue shell on the main console.
2 runlevel2.target Multiuser, without NFS but all other non-GUI services running.
3 multi-user.target runlevel3.target All services running but command line interface (CLI) only.
4 runlevel4.target Unused.
5 graphical.target runlevel5.target multi-user with a GUI.
6 reboot.target runlevel6.target Reboot
default.target This target is always aliased with a symbolic link to either multi-user.target or graphical.target. systemd always uses the default.target to start the system. Standard.target ska aldrig ha som alias halt.target, poweroff.target eller reboot.target.

Tabell 1: Jämförelse av SystemV-körningsnivåer med systemd-mål och vissa målalias.

Varje mål har en uppsättning beroenden som beskrivs i konfigurationsfilen. systemd startar de nödvändiga beroendena. Dessa beroenden är de tjänster som krävs för att köra Linuxvärden på en viss funktionsnivå. När alla beroenden som anges i målkonfigurationsfilerna är inlästa och körs körs systemet på den målnivån.

systemd tittar också på de äldre SystemV-init-katalogerna för att se om det finns några startfiler där. Om så är fallet använder systemd dessa som konfigurationsfiler för att starta de tjänster som beskrivs i filerna. Den föråldrade nätverkstjänsten är ett bra exempel på en av dem som fortfarande använder SystemV-startfiler i Fedora.

Figur 1 nedan är kopierad direkt från man-sidan för bootup. Den visar det allmänna händelseförloppet under systemd-start och de grundläggande ordningskraven för att säkerställa en lyckad start.

Målen sysinit.target och basic.target kan betraktas som kontrollpunkter i startprocessen. Även om systemd har som ett av sina designmål att starta systemtjänster parallellt finns det fortfarande vissa tjänster och funktionella mål som måste startas innan andra tjänster och mål kan startas. Dessa kontrollpunkter kan inte passeras förrän alla tjänster och mål som krävs av den kontrollpunkten är uppfyllda.

Så sysinit.target nås när alla enheter som den är beroende av är klara. Alla dessa enheter, montering av filsystem, inställning av swapfiler, start av udev, inställning av slumpgeneratorfröet, initiering av tjänster på låg nivå och inställning av kryptografiska tjänster om ett eller flera filsystem är krypterade, måste slutföras, men inom sysinit.target kan dessa uppgifter utföras parallellt.

Den sysinit.target startar alla tjänster och enheter på låg nivå som krävs för att systemet ska fungera marginellt och som krävs för att kunna gå vidare till basic.target.

local-fs-pre.target
|
v
(various mounts and (various swap (various cryptsetup
fsck services...) devices...) devices...) (various low-level (various low-level
| | | services: udevd, API VFS mounts:
v v v tmpfiles, random mqueue, configfs,
local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...)
| | | | |
\__________________|_________________ | ___________________|____________________/
\|/
v
sysinit.target
|
____________________________________/|\________________________________________
/ | | | \
| | | | |
v v | v v
(various (various | (various rescue.service
timers...) paths...) | sockets...) |
| | | | v
v v | v rescue.target
timers.target paths.target | sockets.target
| | | |
v \_________________ | ___________________/
\|/
v
basic.target
|
____________________________________/| emergency.service
/ | | |
| | | v
v v v emergency.target
display- (various system (various system
manager.service services services)
| required for |
| graphical UIs) v
| | multi-user.target
| | |
\_________________ | _________________/
\|/
v
graphical.target

Figur 1: Systemd startup map.

När sysinit.target har uppfyllts startar systemd basic.target och startar alla enheter som krävs för att uppfylla det. Basic.target ger en del ytterligare funktionalitet genom att starta enheter som krävs för nästa mål. Dessa inkluderar inställning av saker som sökvägar till olika körbara kataloger, kommunikationssocklar och timers.

Slutligt kan målen på användarnivå, multi-user.target eller graphical.target initialiseras. Observera att multi-user.target måste nås innan beroendena för det grafiska målet kan uppfyllas.

De understrukna målen i figur 1 är de vanliga startmålen. När något av dessa mål nås har uppstarten avslutats. Om multi-user.target är standard, bör du se en inloggning i textläge på konsolen. Om graphical.target är standard bör du se en grafisk inloggning; den specifika GUI-inloggningsskärmen du ser beror på vilken displayhanterare du använder som standard.

Saker

Jag hade nyligen ett behov av att ändra standardstartkärnan på en Linux-dator som använde GRUB2. Jag upptäckte att några av kommandona inte verkade fungera korrekt för mig, eller att jag inte använde dem på rätt sätt. Jag är ännu inte säker på vad som var fallet och måste göra lite mer efterforskningar.

Kommandot grub2-set-default ställde inte korrekt in standardkärnindexet för mig i filen /etc/default/grub så att den önskade alternativa kärnan inte startade. Så jag ändrade manuellt /etc/default/grub GRUB_DEFAULT=saved till GRUB_DEFAULT=2 där 2 är indexet för den installerade kärnan som jag ville starta upp. Sedan körde jag kommandot grub2-mkconfig > /boot/grub2/grub.cfg för att skapa den nya grub-konfigurationsfilen. Detta kringgående fungerade som förväntat och startade till den alternativa kärnan.

Slutsatser

GRUB2 och init-systemet systemd är de viktigaste komponenterna i start- och uppstartsfaserna i de flesta moderna Linuxdistributioner. Trots att det har funnits kontroverser kring speciellt systemd arbetar dessa två komponenter smidigt tillsammans för att först ladda kärnan och sedan starta upp alla de systemtjänster som krävs för att producera ett fungerande Linuxsystem.

Och även om jag tycker att både GRUB2 och systemd är mer komplexa än sina föregångare, är de också lika lätta att lära sig och hantera. Man-sidorna innehåller mycket information om systemd, och på freedesktop.org finns den fullständiga uppsättningen av systemd-man-sidorna online. Se resurserna nedan för fler länkar.