pid_namespaces(7)

NAMN
pid_namespaces — översikt över Linux PID-namnrymder

BESKRIVNING
För en översikt över namnrymder, se namespaces(7).

PID-namnrymder isolerar process-ID-nummerrymden, vilket betyder att processer i olika PID-namnrymder kan ha samma PID. PID-namnrymder gör att behållare kan åstadkomma funktionalitet såsom att stoppa/återuppta uppsättningen av processer i behållaren och migrera behållaren till en ny värd medan processerna inuti behållaren behåller samma PID:ar.

PID:ar i en ny PID-namnrymd börjar på 1, ungefär som ett fristående system, och anrop av fork(2), vfork(2) eller clone(2) kommer skapa processer med PID:ar som är unika inom namnrymden.

Användning av PID-namnrymder kräver en kärna som är konfigurerad med alternativet CONFIG_PID_NS.

  Namnrymdens init-process
Den första processen som skapas i en ny namnrymd (d.v.s., processen som skapas med clone(2) med flaggan CLONE_NEWPID, eller det första barnet som skapas av en process efter ett anrop av unshare(2) med flaggan CLONE_NEWPID) har PID:en 1, och är ”init”-processen för namnrymden (se init(1)). Denna process blir förälder för barnprocesser som blir föräldralösa för att en process som bor i denna PID-namnrymd avslutas (se nedan för ytterligare detaljer).

Om ”init”-processen i en PID-namnrymd avslutas avslutar kärnan alla processerna i namnrymden med en signal SIGKILL. Detta beteende avspeglar faktumet att ”init”-processen är avgörande för den korrekta funktionen hos en PID-namnrymd. I detta fall kommer en senare fork(2) in i denna PID-namnrymd att misslyckas med felet ENOMEM; det är inte möjligt att skapa en ny process i en PID-namnrymd vars ”init”-process har avslutat. Sådana scenarier kan uppstå när, till exempel, en process använder en öppen filbeskrivare för en fil /proc/pid/ns/pid som motsvarar en process som fanns i en namnrymd för att göra setns(2) in i den namnrymden efter att ”init”-processen har avslutat. Ett annat möjligt scenario kan uppstå efter ett anrop av unshare(2): om det första barnet som därefter skapas av en fork(2) avslutar, då misslyckas senare anrop av fork(2) med ENOMEM.

Endast signaler för vilka ”init”-processen har etablerat en signalhanterare kan skickas till ”init”-processen av andra medlemmar av PID-namnrymden. Denna begränsning gäller även för privilegierade processer, och hindrar andra medlemmar av PID-namnrymden från att av misstag döda ”init”-processen.

På liknande sätt kan en process i en anfadernamnrymd — med hänsyn till de vanliga rättighetskontrollerna som beskrivs i kill(2) — skicka signaler till ”init”-processen i en barn-PID-namnrymd endast om ”init”-processen har etablerat en hanterare för den signalen. (Inom hanteraren kommer fältet siginfo_t si_pid som beskrivs i sigaction(2) att vara noll.) SIGKILL eller SIGSTOP hanteras speciellt: dessa signaler skickas tvingande när de skickas från en anfader-PID-namnrymd. Ingendera av dessa signaler kan fångas av ”init”-processen, och kommer därför resultera i de vanliga åtgärderna som associeras med dessa signaler (avslut respektive stopp av processen).

Med början från Linux 3.4 får systemanropet reboot(2) en signal att skickas till namnrymdens ”init”-process. Se reboot(2) för mer detaljer.

  Nästning av PID-namnrymder
PID-namnrymder kan nästas: varje PID-namnrymd har en förälder, utom den intitiala (”rot”) PID-namnrymden. Förälder till en PID-namnrymd är PID-namnrymden för processen som skapade namnrymden med clone(2) eller unshare(2). PID-namnrymder formar alltså ett träd, där alla namnrymder ytterst spårar sitt ursprung till rotnamnrymden. Sedan Linux 3.7 begränsar kärnan det maximala nästningsdjupet för PID-namnrymder till 32.

En process är synlig för andra processer i sin PID-namnrymd, och för processer i varje direkt anfaders-PID-namnrymd hela vägen tillbaka till rot-PID-namnrymden. I detta sammanhang betyder ”synlig” att en process kan vara målet för åtgärder av en annan process med systemanrop som anger ett process-ID. Omvänt, processer i en barn-PID-namnrymd kan inte se processer i föräldranamnrymden och mer avlägsna anfadernamnrymder. Mer koncist: en process kan se (t.ex., skicka signaler till med kill(2), sätta nice-värde på med setpriority(2), etc.) endast processer som ingår i dess egen PID-namnrymd och avkommor av den namnrymden.

En process har ett process-ID i varje lager av PID-namnrymdshierarkin i vilken den är synlig, och går tillbaka genom varje direkt anfadernamnrymd vidare till rot-PID-namnrymden. Systemanrop som verkar på process-ID:er arbetar alltid med användning av process-ID:t som är synligt i anroparens PID-namnrymd. Ett anrop av getpid(2) returnerar alltid PID:en som är associerad med namnrymden i vilken processen skapades.

Några processer i en PID-namnrymd kan ha föräldrar som ligger utanför namnrymden. Till exempel, föräldern till den initiala processen i namnrymden (d.v.s., processen init(1) med PID 1) finns av nödvändighet i en annan namnrymd. På samma sätt finns de direkta barnen till en process som använder setns(2) för att få sina barn att gå med i en PID-namnrymd i en annan PID-namnrymd än den som anropade setns(2). Anrop av getppid(2) för sådana processer returnerar 0.

Medan processer fritt kan gå in i barn-PID-namnrymder (t.ex. med setns(2) med en PID-namnrymdsfilbeskrivare) kan de inte flytta i någon annan riktning. Det vill säga, processer kan inte gå in i någon anfadernamnrymd (förälder, farförälder, etc.). Att byta PID-namnrymder är en envägsåtgärd.

Åtgärden NS_GET_PARENT till ioctl(2) kan användas för att upptäcka föräldrarelationen mellan PID-namnrymder; se ioctl_ns(2).

  semantiken hos setns(2) och unshare(2)
Anrop av setns(2) som anger en PID-namnrymdsfilbeskrivare och anrop av unshare(2) med flagga CLONE_NEWPID får barn som senare skapas av anroparen att placeras i en annan PID-namnrymd än anroparens. (Från Linux 4.12 visas PID-namnrymden via filen /proc/pid/ns/pid_for_children, så som beskrivs i namespaces(7).) Dessa anrop ändrar dock inte PID-namnrymden för den anropande processen, då detta skulle ändra anroparens uppfattning om sin egen PID (så som den rapporteras av getpid()), vilket skulle göra sönder många program och bibliotek.

För att uttrycka saker på ett annat sätt: en process PID-namnrymdsmedlemskap avgörs när processen skapas och kan inte ändras därefter. Bland annat betyder detta att föräldrarelationen mellan processer avspeglar föräldrarelationen mellan PID-namnrymder: föräldern till en process finns antingen i samma namnrymd eller bor i den omedelbara föräldra-PID-namnrymden.

En process kan anropa unshare(2) med flaggan CLONE_NEWPID endast en gång. Efter att den utfört denna åtgärd kommer dess symboliska länk /proc/pid/ns/pid_for_children att vara tom tills det första barnet är skapat i namnrymden.

  Adoption av föräldralösa barn
När en barnprocess blir föräldralös flyttas den över till ”init”-processen i PID-namnrymden för dess förälder (om inte en av de närmare anfäderna till föräldern har använt kommandot prctl(2) PR_SET_CHILD_SUBREAPER för att markera sig själv som den som skördar avkommeprocesser som blir föräldralösa). Observera att på grund av semantiken hos setns(2) och unshare(2) som beskrivs ovan kan detta vara ”init”-processen i PID-namnrymden som är förälder till barnets PID-namnrymd, istället för ”init”-processen i barnets egen PID-namnrymd.

  Kompatibilitet hos CLONE_NEWPID med andra CLONE_*-flaggor
I de nuvarande versionerna av Linux kan inte CLONE_NEWPID kombineras med CLONE_THREAD. Trådar måste befinna sig i samma PID-namnrymd så att de kan skicka signaler till varandra. Vidare måste det vara möjligt att se alla trådarna hos en process i filsystemet proc(5). Dessutom, om två trådar skulle vara i olika PID-namnrymder skulle inte process-ID:t för processen som skickar en signal kunna kodas på ett meningsfullt sätt när en signal skickas (se beskrivningen av typen siginfo_t i sigaction(2)). Eftersom detta beräknas när en signal köas upp skulle en signalkö delad mellan processer i flera PID-namnrymder omöjliggöra det.

I tidigare versioner av Linux var dessutom CLONE_NEWPID inte tillåtet (misslyckades med felet EINVAL) i kombination med CLONE_SIGHAND (före Linux 4.3) såväl som CLONE_VM (före Linux 3.12). Ändringarna som lyfte dessa begränsningar har även porterats till tidigare stabila kärnor.

  /proc och PID-namnrymder
Ett /proc-filsystem visar (i katalogerna /proc/pid) endast processer som är synliga i PID-namnrymden för processen som utför monteringen, även om /proc visas för processer i andra namnrymder.

Efter att ha skapat en ny PID-namnrymd är det bra för barnet att byta sin rotkatalog och montera en ny procfs-instans på /proc så att verktyg såsom ps(1) fungerar korrekt. Om en ny monteringsnamnrymd skapas samtidigt genom att inkludera CLONE_NEWNS i argumentet flaggor till clone(2) eller unshare(2), då är det inte nödvändigt att byta rotkatalog: en ny procfs-instans kan monteras direkt över /proc.

Från ett skal är kommandot för att montera /proc:

    $ mount -t proc proc /proc

Att anropa readlink(2) på sökvägen /proc/self ger process-ID:t för anroparen i den procfs-monteringens PID-namnrymd (d.v.s., PID-namnrymden för processen som monterade procfs). Detta kan vara användbart för introspektionsändamål, när en process vill veta sin PID i andra namnrymder.

  /proc-filer

/proc/sys/kernel/ns_last_pid (från Linux 3.3)
    Denna fil (som är virtualiserad per PID-namnrymd) visar den senaste PID:en som allokerades i denna PID-namnrymd. När nästa PID allokeras kommer kärnan söka efter den lägsta oallokerade PID:en som är större än detta värde, och när denna fil därefter läses kommer den visa den PID:en.

    Denna fil kan skrivas av en process som har förmågan CAP_SYS_ADMIN eller (från Linux 5.9) CAP_CHECKPOINT_RESTORE inuti användarnamnrymden som äger PID-namnrymden. Detta gör det möjligt att bestämma PID:en som allokeras för nästa process som skapas inuti denna PID-namnrymd.

  Diverse
När ett process-ID skickas över ett UNIX-domänsuttag till en process i en annan PID-namnrymd (se beskrivningen av SCM_CREDENTIALS i unix(7)) översätts den till det motsvarande PID-värdet i den mottagande processens PID-namnrymd.

STANDARDER
Linux.

EXEMPEL
Se user_namespaces(7).

SE ÄVEN
clone(2), reboot(2), setns(2), unshare(2), proc(5), capabilities(7), credentials(7), mount_namespaces(7), namespaces(7), user_namespaces(7), switch_root(8)

ÖVERSÄTTNING
Den svenska översättningen av denna manualsida skapades av Göran Uddeborg <goeran@uddeborg.se>

Denna översättning är fri dokumentation; läs GNU General Public License Version 3 (https://www.gnu.org/licenses/gpl-3.0.html) eller senare för upphovsrättsvillkor. Vi tar INGET ANSVAR.

Om du hittar fel i översättningen av denna manualsida, skicka ett mail till Tp-sv@listor.tp-sv.se.