.\" -*- coding: UTF-8 -*- .\" Copyright 2016, International Business Machines Corp. .\" Copyright 2017, Michael Kerrisk .\" Copyright, the authors of the Linux man-pages project .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH userfaultfd 2 "8. februar 2026" "Linux man\-pages 6.17" .SH NAVN userfaultfd \- opret en fildeskriptor til at håndtere sidefejl i brugerrum .SH BIBLIOTEK C\-standardbibliotek (\fIlibc\fP,\ \fI\-lc\fP) .SH SYNOPSIS .nf \fB#include \fP /* Definition af \fBO_*\fP\-konstanter */ \fB#include \fP /* Definition af \fBSYS_*\fP\-konstanter */ \fB#include \fP /* Definition af \fBUFFD_*\fP\-konstanter */ \fB#include \fP .P \fBint syscall(SYS_userfaultfd, int \fP\fIflag\fP\fB);\fP .fi .P \fINote\fP: glibc tilbyder intet omslag for \fBuserfaultfd\fP(), så det er nødvendigt at bruge \fBsyscall\fP(2). .SH BESKRIVELSE \fBuserfaultfd\fP() opretter et nyt userfaultfd\-objekt, der kan bruges til uddelegering af side\-fejl håndtering til et brugerrumsprogram og returnerer en fildeskriptor, der referer til det nye objekt. Det nye userfaultfd\-objekt er konfigureret via \fBioctl\fP(2). .P Når først userfaultfd\-objektet er konfigureret, så kan programmet bruge \fBread\fP(2) til at modtage userfauldtfd\-påmindelser. Læsningerne fra userfaultfd kan være blokernede eller ikkeblokerende, afhængig af værdien af \fIflag\fP brugt til oprettelsen af userfaultfd eller efterfølgende kald til \fBfcntl\fP(2). .P De følgende værdier kan være bitvis ORed i \fIflag\fP for at ændre opførelsen for \fBuserfaultfd\fP(): .TP \fBO_CLOEXEC\fP Aktiver flaget close\-on\-exec for den nye userfaultfd\-fildeskiptor. Se beskrivelsen af flaget \fBO_CLOEXEC\fP i \fBopen\fP(2). .TP \fBO_NONBLOCK\fP Aktiverer ikkeblokerende operation for userfaultfd\-objektet. Se beskrivelsen af flaget \fBO_NONBLOCK\fP i \fBopen\fP(2). .TP \fBUFFD_USER_MODE_ONLY\fP Dette er et userfaultfd\-specifikt flag, der blev introduceret i Linux 5.11. Når angivet vil userfaultfd\-objektet kun kunne håndtere sidefejl med oprindelse i brugerrummet på de registrerede regioner. Når en kerne\-oprindelsesfejl bliver udløst på det registerede interval med denne userfaultdfd, så vil et \fBSIGBUS\fP\-signal blive leveret. .P .\" Når den sidste fildeskriptor refererende til et userfaultfd\-objekt er lukket, bliver alle hukommelsesintervallerne, der var registreret med objekter, afregistreret og ulæste hændelser tømmes. .P Userfaultfd understøtter tre tilstande for registrering: .TP \fBUFFDIO_REGISTER_MODE_MISSING\fP (siden Linux 4.10) Når registreret med tilstanden \fBUFFDIO_REGISTER_MODE_MISSING\fP vil brugerrummet modtage en side\-fejl påmindelse, når en manglende side tilgås. Den fejlede tråd vil blive stoppet fra afvikling indtil sidefejlen er løst fra brugerrum af enten en \fBUFFDIO_COPY\fP eller en \fBUFFDIO_ZEROPAGE\fP ioctl. .TP \fBUFFDIO_REGISTER_MODE_MINOR\fP (siden Linux 5.13) Når registreret med tilstanden \fBUFFDIO_REGISTER_MODE_MINOR\fP vil brugerrummet modtage en side\-fejl påmindelse, når en mindre sidefejl opstår. Det vil sige når bagsiden er i sidens cache, men sidetabelelementerne endnu ikke findes. Den fejlede tråd vil blive stoppet fra afvikling indtil sidefejlen er løst fra brugerrum af \fBUFFDIO_CONTINUE\fP ioctl. .TP \fBUFFDIO_REGISTER_MODE_WP\fP (siden Linux 5.7) Når registreret med tilstanden \fBUFFDIO_REGISTER_MODE_WP\fP vil brugerrummet modtage en side\-fejl påmindelse, når en skrivebeskyttet side skrives. Den fejlede tråd vil blive stoppet fra afvikling indtil brugerrummet fjerne skrivebeskyttelsen for siden via en \fBUFFDIO_WRITEPROTECT\fP ioctl. .P Flere tilstande kan aktiveres på samme tid for det samme hukommelsesinterval. .P Siden Linux 4.14 kan en userfaultfd\-sidefejlpåmindelse selektivt indlejre fejlende tråd\-id\-information i påmindelsen. Man skal eksplicit aktivere denne funktion via \fBUFFD_FEATURE_THREAD_ID\fP\-bit når userfaultfd\-konteksten initialiseres. Som standard er tråd\-id\-rapportering deaktiveret. .SS Brug Userfaultfd\-mekanismen er designet til at tillade at en tråd i et flertrådet program kan udføre en brugerrums søgning for andre tråde i processen. Når en sidefejl opstår for en af regionerne registreret med userfaultfd\-objektet, så lægges den fejlende tråd i søvn og en hændelse oprettes, der kan læses via userfaultfd\-fildeskriptoren. Den fejlhåndterende tråd læser hændelser fra denne fildeskriptor og betjener dem via operationerne beskrivet i \fBioctl_userfaultfd\fP(2). Under betjening af sidefejlhændelser kan den fejlhåndterende tråd udløse en vækning for den sovende tråd. .P Det er muligt for de fejlende tråde og de fejlhåndterende tråde at køre i konteksten af forskellige processer. I dette tilfælde, kan disse tråde tilhøre forskellige programmer, og programmet der afvikler de fejlende tråde vil ikke nødvendigvis samarbejde med programmet, der håndterer sidefejlene. I sådan ikkesamarbejdende tilstand skal processen der overvåger userfaultfd og håndterer sidefjel være opmærksom på ændringer i det virtuelle hukommelseslayout for den fejlende proces for at undgå hukommelseskorruption. .P Siden Linux 4.11 kan userfaultfd også påminde de fejlhåndterende tråde om ændringer i det virtuelle hukommelseslayout for den fejlende proces. Derudover hvis den fejlende proces igangsætter \fBfork\fP(2), kan userfaultfd\-objekterne associeret med overprocessen måske blive duplikeret i underprocessen og userfaultfd\-overvågeren vil blive påmindet (via \fBUFFD_EVENT_FORK\fP beskrevet nedenfor) om fildeskriptoren associeret med userfault\-objekterne opretter for underprocessen, der gør det muligt for userfaultfd\-overvågeren at udføre brugerrumssøgning for underprocessen. Til forskel fra sidefejl der skal være synkrone og kræver en eksplicit eller implicit opvækning så leveres alle andre objekter asynkront og den ikkesamarbejdende proces genoptager afvikling så snart userfaultfd\-håndteringen afvikler \fBread\fP(2). Userfaultfd\-håndteringen bør omhyggeligt synkronisere kald til \fBUFFDIO_COPY\fP med behandlingen af hændelser. .P .\" Regarding the preceding sentence, Mike Rapoport says: .\" The major point here is that current events delivery model could be .\" problematic for multi-threaded monitor. I even suspect that it would be .\" impossible to ensure synchronization between page faults and non-page .\" fault events in multi-threaded monitor. .\" .P .\" FIXME elaborate about non-cooperating mode, describe its limitations .\" for kernels before Linux 4.11, features added in Linux 4.11 .\" and limitations remaining in Linux 4.11 .\" Maybe it's worth adding a dedicated sub-section... .\" Den nuværende asynkrone model for hændelseslevering er optimal for enkelttrådede ikkesamarbejdende userfaultfd\-håndteringsimplementeringer. .P .\" Siden Linux 5.7 kan userfaultfd udføre synkron synkron sporing af beskidte sider via den nye skrivebeskyttede registertilstand. Man bør tjekke mod funktionsbit'en \fBUFFD_FEATURE_PAGEFAULT_FLAG_WP\fP før denne funktion anvendes. Svarende til den oprindelige userfaultfd missing\-tilstand vil den skrivebeskyttede tilstand oprette en userfaultfd\-påmindelse, når den beskyttede side skrives. Brugeren skal løse sidefejlen ved at fjerne beskyttelsen for den fejlende side og sparke den fejlede tråd i gang igen. For yderligere information kan du se i afsnittet »Userfaultfd write\-protect\-tilstand«. .SS Userfaultfd\-operation Efter userfaultfd\-objektet er oprettet med \fBuserfaultfd\fP(), skal programmet aktivere det via operationen \fBUFFDIO_API\fP \fBioctl\fP(2). Denne operation tillader et totrins handskake (håndtryk) mellem kernen og brugerummet for at bestemme hvilken API\-verison og funktioner kernen understøtte, så aktivere de funktioner brugerummet ønsker. Denne operation skal udføres før nogle af \fBioctl\fP(2)\-operationerne beskrevet nedenfor (eller disse operationer fejler med fejlen \fBEINVAL\fP). .P Efter en succesfuld \fBUFFDIO_API\fP\-operation registrerer programmet hukommelsesadresseintervallerne via \fBUFFDIO_REGISTER\fP \fBioctl\fP(2)\-operationen. Efter en succesfuld fuldførelse af en \fBUFFDIO_REGISTER\fP\-operation opstår der en sidefejl i det anmodte hukommelsesinterval og tilfredsstillende tilstanden defineret på registreringstidspunktet, vil blive omdirigeret af kernen til brugerrumsprogrammet. Programmet kan så bruge diverse (f.eks. \fBUFFDIO_COPY\fP, \fBUFFDIO_ZEROPAGE\fP eller \fBUFFDIO_CONTINUE\fP) \fBioctl\fP(2)\-operationer til at løse sidefejlen. .P Siden Linux 4.14, hvis programmet angiver funktionsbit'en \fBUFFD_FEATURE_SIGBUS\fP ved at bruge \fBUFFDIO_API\fP \fBioctl\fP(2), så vil ingen side\-fejl påmindelse blive omdirigeret til brugerrum. I stedet leveres et \fBSIGBUS\fP\-signal til den fejlende proces. Med denne funktion kan userfaultfd bruges til robusthedsformål til at fange enhver adgang til et område i det registrerede adresseinterval, der ikke har sider allokeret, uden at skulle lytte til userfaultfd\-hændelser. Ingen userfaultfd\-overvågning vil være krævet for at håndtere sådanne hukommelsesadgange. For eksempel kan denne funktion være nyttig for programmer, der ønsker at forhindre kernen i automatisk at allokere sider og udfylde huller i ikkesammenhængende filer, når hullet tilgåes via en hukommelsesoversættelse. .P Funktionen \fBUFFD_FEATURE_SIGBUS\fP arves implicit via \fBfork\fP(2) hvis brugt sammen med \fBUFFD_FEATURE_FORK\fP. .P Detaljer for de forskellige \fBioctl\fP(2)\-operationer kan findes i \fBioctl_userfaultfd\fP(2). .P Siden Linux 4.11, kan hændelser udover side\-fejl aktiveret under \fBUFFDIO_API\fP\-operationen. .P .\" Op til Linux 4.11 kan userfaultfd kun bruges med anonyme private hukommelsesoversættelser. Siden Linux 4.11 kan userfaultfd også bruges med hugetlbfs og delte hukommelsesoversættelser. .SS "Userfaultfd write\-protect\-tilstand (siden Linux 5.7)" Siden Linux 5.7 understøtter userfaultfd skrivebeskyttet tilstand for anonym hukommelse. Brugeren skal først tjekke tilgængelighed for denne funktion via \fBUFFDIO_API\fP ioctl mod funktionsbit'en \fBUFFD_FEATURE_PAGEFAULT_FLAG_WP\fP før denne funkton bruges. .P Siden Linux 5.19 var den skrivebeskyttede tilstand også understøttet på shmem\- og hugetlbfs\-hukommelsestyper. Den kan registreres med funktionsbit'en \fBUFFD_FEATURE_WP_HUGETLBFS_SHMEM\fP. .P For at registrere med userfaultfd i skrivebeskyttet tilstand skal brugeren initialisere \fBUFFDIO_REGISTER\fP ioctl med tilstanden \fBUFFDIO_REGISTER_MODE_WP\fP angivet. Bemærk at det er legalt at overvåge det samme hukommelsesinterval med flere tilstande. For eksempel kan brugeren bruge \fBUFFDIO_REGISTER\fP med tilstanden angivet til \fBUFFDIO_REGISTER_MODE_MISSING | UFFDIO_REGISTER_MODE_WP\fP. Når der kun er \fBUFFDIO_REGISTER_MODE_WP\fP registreret vil brugerrummet \fIikke\fP modtage nogen påmindelse når en manglende side skrives. I stedet vil brugerrummet kun modtage en skrivebeskyttet side\-fejl påmindelse, når en eksisterende men skrivebeskyttet side blev skrevet. .P Efter \fBUFFDIO_REGISTER\fP ioctl fuldførtes med \fBUFFDIO_REGISTER_MODE_WP\fP\-tilstanden angivet, kan brugeren skrivebeskytte enhver eksisterende hukommelse i intervallet, der bruger ioctl \fBUFFDIO_WRITEPROTECT\fP hvor \fIuffdio_writeprotect.mode\fP bør være angivet til \fBUFFDIO_WRITEPROTECT_MODE_WP\fP. .P Når en skrivebeskyttet hændelse opstår, så vil brugerrummet modtage en side\-fejl påmindelse hvis \fIuffd_msg.pagefault.flags\fP vil være med \fBUFFD_PAGEFAULT_FLAG_WP\fP\-flaget angivet. Bemærk: da kun skrivninger kan udløse denne slags fjel, vil skrivebeskyttede påmindelser altid have \fBUFFD_PAGEFAULT_FLAG_WRITE\fP\-bit'en angivet sammen med \fBUFFD_PAGEFAULT_FLAG_WP\fP\-bit'en. .P .\" For at løse en skrivebeskyttet sidefejl bør brugeren initiere endnu en \fBUFFDIO_WRITEPROTECT\fP ioctl, hvis \fIuffd_msg.pagefault.flags\fP skal have flaget \fBUFFDIO_WRITEPROTECT_MODE_WP\fP ryddet på den fejlende side eller interval. .SS "Userfaultfd minor fault\-tilstand (siden Linux 5.13)" Siden Linux 5.13 understøtter userfaultfd minor fault\-tilstand. I denne tilstand fremstilles fejlbeskeder ikke for væsentlige fejl (hvor siden manglede), men derimod mindre fejl, hvor en side findes i sidemellemlageret, men sidetabelelementerne er endnu ikke til stede. Brugeren skal først tjekke tilgængelighed for denne funktion via \fBUFFDIO_API\fP ioctl med det passende funktionsbitsæt før denne funktion bruges: \fBUFFD_FEATURE_MINOR_HUGETLBFS\fP siden Linux 5.13, eller \fBUFFD_FEATURE_MINOR_SHMEM\fP siden Linux 5.14. .P For at registrere med userfaultfd minor fault\-tilstanden skal brugeren igangsætte \fBUFFDIO_REGISTER\fP ioctl med tilstanden \fBUFFD_REGISTER_MODE_MINOR\fP angivet. .P Når der opstår en mindre fejl vil brugerrummet modtage en side\-fejl\-påmindelse hvis \fIuffd_msg.pagefault.flags\fP vil have flaget \fBUFFD_PAGEFAULT_FLAG_MINOR\fP angivet. .P For at løse en mindre sidefejl bør håndteringen beslutte hvorvidt det eksisterende sideindhold først skal ændres. Hvis det skal, så skal det gøres via en anden, ikke\-userfaultfd\-registreret oversættelse til den samme bagside (f.eks. ved at oversætte shmem\- eller hugetlbfs\-filen to gange). Når først siden ses som »opdateret« kan fejlen løses ved at initiere \fBUFFDIO_CONTINUE\fP ioctl, der installerer sidetabelelementerne og (som standard) vækker de fejlende tråde. .P .\" Minor fault\-tilstanden understøtter kun hugetlbfs\-understøttet (siden Linux 5.13) og shmem\-understøttet (siden Linux 5.14) hukommelse. .SS "Læsning fra userfaultfd\-strukturen" Hver \fBread\fP(2) fra userfaultfd\-fildeskriptoren returnerer en eller flere \fIuffd_msg\fP\-strukturer, der hver beskriver en side\-fejl hændelse eller en hændelse krævet for den ikke\-samarbejdende userfaultfd\-brug: .P .in +4n .EX struct uffd_msg { __u8 event; /* Hændelsestype */ ... union { struct { __u64 flags; /* Flag der beskriver fejl */ __u64 address; /* Fejlende adresse */ union { __u32 ptid; /* Tråd\-id for fejlen */ } feat; } pagefault; \& struct { /* Siden Linux 4.11 */ __u32 ufd; /* Userfault\-fildeskriptor for underprocessen */ } fork; \& struct { /* Siden Linux 4.11 */ __u64 from; /* Gammel adresse for omfordelt område */ __u64 to; /* Ny adresse for omfordelt område */ __u64 len; /* Oprindelig oversættelsesstørrelse */ } remap; \& struct { /* Siden Linux 4.11 */ __u64 start; /* Startadresse for fjernet område */ __u64 end; /* Slutadresse for fjernet område */ } remove; ... } arg; \& /* Mellemrumsfelter udeladt */ } __packed; .EE .in .P Hvis flere hændelser er tilgængelige og det angivne mellemlager er stort nok, så returnerer \fBread\fP(2) så mange hændelser som passer ind i det angivne mellemlager. Hvis mellemlageret angivet for \fBread\fP(2) er mindre end størrelsen på \fIuffd_msg\fP\-strukturen, så fejler \fBread\fP(2) med fejlen \fBEINVAL\fP. .P Felterne angivet i strukturen \fIuffd_msg\fP er som følgende: .TP \fIevent\fP Hændelsestypen. Afhængig af hændelsestypen repræsenterer forskellige felter for \fIarg\fP\-foreningen detaljer krævet for hændelsesbehandlingen. Hændelser for ikke\-page\-fault oprettes kun når passende funktion er aktiveret under API\-håndtrykket med \fBUFFDIO_API\fP \fBioctl\fP(2). .IP De følgende værdier kan fremgå af feltet \fIevent\fP: .RS .TP \fBUFFD_EVENT_PAGEFAULT\fP (siden Linux 4.3) En sidefejl\-hændelse. Sidefejl\-detaljer er tilgængelige i feltet \fIpagefault\fP. .TP \fBUFFD_EVENT_FORK\fP (siden Linux 4.11) .\" FIXME describe duplication of userfault file descriptor during fork Oprettet når den fejlende proces igangsætter \fBfork\fP(2) (eller \fBclone\fP(2) uden flaget \fBCLONE_VM\fP). Hændelsesdetaljerne er tilgængelige i feltet \fIfork\fP. .TP \fBUFFD_EVENT_REMAP\fP (siden Linux 4.11) Oprettet når den fejlende proces igangsætter \fBmremap\fP(2). Hændelsesdetaljerne er tilgængelig i feltet \fIremap\fP. .TP \fBUFFD_EVENT_REMOVE\fP (siden Linux 4.11) Oprettet når den fejlende proces igangsætter \fBmadvise\fP(2) med rådet \fBMADV_DONTNEED\fP eller \fBMADV_REMOVE\fP. Hændelsesdetaljerne er tilgængelige i feltet \fIremove\fP. .TP \fBUFFD_EVENT_UNMAP\fP (siden Linux 4.11) Oprettet når den fejlende proces fjerner kortlægning af et hukommelsesinterval, enten eksplicit via \fBmunmap\fP(2) eller implicit under \fBmmap\fP(2) eller \fBmremap\fP(2). Hændelsesdetaljerne er tilgængelige i feltet \fIremove\fP. .RE .TP \fIpagefault.address\fP Adressen der udløste sidefejlen. .TP \fIpagefault.flags\fP En bit\-maske af flag, der beskriver hændelsen. For \fBUFFD_EVENT_PAGEFAULT\fP, kan det følgende flag måske fremgå: .RS .TP \fBUFFD_PAGEFAULT_FLAG_WP\fP Hvis dette flag er angivet, så var fejlen en skrivebeskyttelse. .TP \fBUFFD_PAGEFAULT_FLAG_MINOR\fP Hvis dette flag er angivet, så var fejlen en mindre fejl. .TP \fBUFFD_PAGEFAULT_FLAG_WRITE\fP Hvis dette flag er angivet, så var fejlen en skrivefejl. .P Hvis hverken \fBUFFD_PAGEFAULT_FLAG_WP\fP eller \fBUFFD_PAGEFAULT_FLAG_MINOR\fP er angivet, så var fejlen en manglende fejl. .RE .TP \fIpagefault.feat.pid\fP Tråd\-id'et der udløste sidefejlen. .TP \fIfork.ufd\fP Fildeskriptoren associeret med brugerfejlobjektet oprettet for underprocesen oprettet af \fBfork\fP(2). .TP \fIremap.from\fP Den oprindelige adresse for hukommelsesintervallet, der blev omarrangeret via \fBmremap\fP(2). .TP \fIremap.to\fP Den nye adresse for hukommelsesintervallet, der blev omarrangeret via \fBmremap\fP(2). .TP \fIremap.len\fP Den oprindelige størrelse på hukommelsesintervallet, der blev omarrangeret via \fBmremap\fP(2). .TP \fIremove.start\fP Startadressen for hukommelsesintervallet, der blev frigjort via \fBmadvise\fP(2) eller ej arrangeret .TP \fIremove.end\fP Slutadressen for hukommelsesintervallet, der blev frigjort via \fBmadvise\fP(2) eller ej arrangeret .P Som \fBread\fP(2) på en userfaultfd kan en fildeskriptor fejle med de følgende fejl: .TP \fBEINVAL\fP Userfaultfd\-objektet er endnu ikke blevet aktiveret via \fBUFFDIO_API\fP \fBioctl\fP(2)\-operationen .P .\" FIXME What is the reason for this seemingly odd behavior with respect .\" to the O_NONBLOCK flag? (see userfaultfd_poll() in fs/userfaultfd.c). .\" Something needs to be said about this. Hvis flaget \fBO_NONBLOCK\fP er aktiveret i den associerede åbne filbeskrivelse, kan userfaultfd\-fildeskriptoren overvåges med \fBpoll\fP(2), \fBselect\fP(2) og \fBepoll\fP(7). Når hændelser er tilgængelige indikerer fildeskriptoren at den kan læses. Hvis flaget \fBO_NONBLOCK\fP ikke er aktiveret, så indikerer \fBpoll\fP(2) (altid) at filen har en \fBPOLLERR\fP\-betingelse og \fBselect\fP(2) indikerer fildeskriptoren som både læs\- og skrivbar. .SH RETURVÆRDI Ved succes returnerer \fBuserfaultfd\fP() en ny fildeskriptor, der refererer til userfaultfd\-objektet. Ved fejl returneres \-1 og \fIerrno\fP angives for at indikere fejlen. .SH FEJL .TP \fBEINVAL\fP En ej understøttet værdi var angivet i \fIflag\fP. .TP \fBEMFILE\fP Per proces\-begrænsningen på antallet af åbne fildeskriptorer, der er nået .TP \fBENFILE\fP Systemets begrænsning på det samlede antal åbne filer er nået. .TP \fBENOMEM\fP Utilstrækkelig kernehukommelse var tilgængelig. .TP \fBEPERM\fP (siden Linux 5.2) .\" cefdca0a86be517bc390fc4541e3674b8e7803b0 Kalderen er ikke privilegeret (har ikke en \fBCAP_SYS_PTRACE\fP\-kapacitet i det oprindelige brugernavnerum), og \fI/proc/sys/vm/unprivileged_userfaultfd\fP har værdien 0. .SH STANDARDER Linux. .SH HISTORIK Linux 4.3. .P Understøttelse for hugetlbfs og delte hukommelsesområder og ej\-side\-fejl\-hændelser blev tilføjet i Linux 4.11 .SH NOTER Userfaultfd\-mekanismen kan bruges som et alternativ til de traditonelle brugerrumssideteknikker baseret på brugen af signalet \fBSIGSEGV\fP og \fBmmap\fP(2). Kan også bruges til at implementere lazy restore for checkpoint/restore\-mekanismer, samt post\-copy\-migrering for at tillade (næsten) uforstyrret afvikling under overførsel af virtuelle maskiner og Linux\-containere fra en vært til en anden. .SH FEJL Hvis \fBUFFD_FEATURE_EVENT_FORK\fP er aktiveret og et systemkald fra \fBfork\fP(2)\-familien afbrydes af et signal eller fejl kan en gammel userfaultfd\-deskriptor blive oprettet. I dette tilfælde vil en falsk \fBUFFD_EVENT_FORK\fP blive leveret til userfaultfd\-overvågeren. .SH EKSEMPLER Programmet nedenfor demonstrerer brugen af userfaultfd\-mekanismen. Programmet opretter to tråde, en fungerer som side\-fejl\-håndteringen for processen, for siderne i en demand\-page zero\-region oprettet via \fBmmap\fP(2). .P Programmet bruger et kommandolinjeargument, hvilket er antallet af sider, der vil blive oprettet i en oversættelse, hvis sidefejl vil blive håndteret via userfaultfd. Efter oprettelse af et userfaultfd\-objekt opretter programmet en anoynm privat oversættelse af den angivne størrelse og registerer adresseintervallet for den oversættelse via operationen \fBUFFDIO_REGISTER\fP \fBioctl\fP(2). Programmet opretter så endnu en tråd, der vil udføre opgaven med at håndtere sidefejl. .P Hovedtråden løber så igennem siderne for oversættelsen ved at hente byte fra successive sider. Da siderne endnu ikke er blevet tilgået vil den første adgang af en byte i hver side udløse en side\-fejl\-hændelse på userfaultfd\-fildeskriptoren. .P Hver af side\-fejl\-hændelserne håndteres af den anden tråd, der befinder sig i en løkke, der behandler data fra userfaultfd\-fildeskriptoren. I hver løkke\-gennemgang, kalder den anden tråd først \fBpoll\fP(2) for at tjekke tilstanden for fildeskriptoren, og læser så en hændelse fra fildeskriptoren. Alle sådanne hændelser bør være \fBUFFD_EVENT_PAGEFAULT\fP\-hændelser, som tråden håndterer ved at kopiere en side med data ind i den fejlende region via operationen \fBUFFDIO_COPY\fP \fBioctl\fP(2). .P Det følgende er et eksempel på hvad vi ser, når programmet afvikles: .P .in +4n .EX $\fB ./userfaultfd_demo 3\fP; Address returned by mmap() = 0x7fd30106c000 \& fault_handler_thread(): poll() returns: nready = 1; POLLIN = 1; POLLERR = 0 UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fd30106c00f (uffdio_copy.copy returned 4096) Read address 0x7fd30106c00f in main(): A Read address 0x7fd30106c40f in main(): A Read address 0x7fd30106c80f in main(): A Read address 0x7fd30106cc0f in main(): A \& fault_handler_thread(): poll() returns: nready = 1; POLLIN = 1; POLLERR = 0 UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fd30106d00f (uffdio_copy.copy returned 4096) Read address 0x7fd30106d00f in main(): B Read address 0x7fd30106d40f in main(): B Read address 0x7fd30106d80f in main(): B Read address 0x7fd30106dc0f in main(): B \& fault_handler_thread(): poll() returns: nready = 1; POLLIN = 1; POLLERR = 0 UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fd30106e00f (uffdio_copy.copy returned 4096) Read address 0x7fd30106e00f in main(): C Read address 0x7fd30106e40f in main(): C Read address 0x7fd30106e80f in main(): C Read address 0x7fd30106ec0f in main(): C .EE .in .SS Programkilde .\" SRC BEGIN (userfaultfd.c) \& .EX /* userfaultfd_demo.c \& Udgivet under GNU General Public License version 2 eller senere. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include \& static int page_size; \& static void * fault_handler_thread(void *arg) { long uffd; /* userfaultfd\-fildeskriptor */ \& static int fault_cnt = 0; /* Fejlantal håndteret indtil videre */ static char *page = NULL; static struct uffd_msg msg; /* Data læst fra userfaultfd */ \& uffd = (long) arg; \& /* Opret en side der vil blive kopieret ind i den fejlende region. */ \& if (page == NULL) { page = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, \-1, 0); if (page == MAP_FAILED) err(EXIT_FAILURE, "mmap"); } \& /* Løkke, der håndterer indgående hændelser på userfaultfd\- fildeskriptoren. */ \& for (;;) { int nready; ssize_t nread; struct pollfd pollfd; struct uffdio_copy uffdio_copy; \& /* Se hvad poll() fortæller os om userfaultfd. */ \& pollfd.fd = uffd; pollfd.events = POLLIN; nready = poll(&pollfd, 1, \-1); if (nready == \-1) err(EXIT_FAILURE, "poll"); \& printf("\[rs]nfault_handler_thread():\[rs]n"); printf(" poll() returns: nready = %d; " "POLLIN = %d; POLLERR = %d\[rs]n", nready, (pollfd.revents & POLLIN) != 0, (pollfd.revents & POLLERR) != 0); \& /* Læs en hændelse fra userfaultfd. */ \& nread = read(uffd, &msg, sizeof(msg)); if (nread == 0) { printf("EOF on userfaultfd!\[rs]n"); exit(EXIT_FAILURE); } \& if (nread == \-1) err(EXIT_FAILURE, "read"); \& /* Vi forventer kun en slags hændelse; verificer den antagelse. */ \& if (msg.event != UFFD_EVENT_PAGEFAULT) { fprintf(stderr, "Unexpected event on userfaultfd\[rs]n"); exit(EXIT_FAILURE); } \& /* Vis info om side\-fejl\-hændelsen. */ \& printf(" UFFD_EVENT_PAGEFAULT event: "); printf("flags = %"PRIx64"; ", msg.arg.pagefault.flags); printf("address = %"PRIx64"\[rs]n", msg.arg.pagefault.address); \& /* Kopier siden peget mod af \[aq]page\[aq] ind i den fejlende region. Varier indholdet der kopieres ind, så det er mere indlysende at hver fejl håndteres separat. */ \& memset(page, \[aq]A\[aq] + fault_cnt % 20, page_size); fault_cnt++; \& uffdio_copy.src = (unsigned long) page; \& /* Vi skal håndtere sidefejl i sideenheder(!). Så afrund fejlende adresse ned til sidegrænsen. */ \& uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address & \[ti](page_size \- 1); uffdio_copy.len = page_size; uffdio_copy.mode = 0; uffdio_copy.copy = 0; if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == \-1) err(EXIT_FAILURE, "ioctl\-UFFDIO_COPY"); \& printf(" (uffdio_copy.copy returned %"PRId64")\[rs]n", uffdio_copy.copy); } } \& int main(int argc, char *argv[]) { int s; char *addr; /* Start på region håndteret af userfaultfd */ long uffd; /* userfaultfd\-fildeskriptor */ size_t size, i; /* Regionstørrelse håndteret af userfaultfd */ pthread_t thr; /* Id for tråd der håndterer sidefejl */ struct uffdio_api uffdio_api; struct uffdio_register uffdio_register; \& if (argc != 2) { fprintf(stderr, "Usage: %s num\-pages\[rs]n", argv[0]); exit(EXIT_FAILURE); } \& page_size = sysconf(_SC_PAGE_SIZE); size = strtoull(argv[1], NULL, 0) * page_size; \& /* Opret og aktiver userfaultfd\-objekt. */ \& uffd = syscall(SYS_userfaultfd, O_CLOEXEC | O_NONBLOCK); if (uffd == \-1) err(EXIT_FAILURE, "userfaultfd"); \& /* BEMÆRK: To\-trins funktionen handshake (håndtryk) er ikke krævet her da dette eksempel ikke kræver nogle specifikke funktioner. \& Programmer der *skal* dette bør kalde UFFDIO_API to gange: en gang med »features = 0« for at registrere funktioner understøttet af denne kerne og igen med undersættet af funktionerne programmet faktisk ønsker at aktivere. */ uffdio_api.api = UFFD_API; uffdio_api.features = 0; if (ioctl(uffd, UFFDIO_API, &uffdio_api) == \-1) err(EXIT_FAILURE, "ioctl\-UFFDIO_API"); \& /* Opret en privat anonym oversættelse. Hukommelsen vil være demand\-zero paged \- det vil side enndu ikke allokeret. Når vi reelt rører hukommelsen, så vil den blive allokeret via userfaultfd. */ \& addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, \-1, 0); if (addr == MAP_FAILED) err(EXIT_FAILURE, "mmap"); \& printf("Address returned by mmap() = %p\[rs]n", addr); \& /* Registrer hukommelsesintervallet for oversættelsen vi lige oprettede til at blive håndteret af userfaultfd\-objektet. I tilstand, anmoder vi om at registrere manglende sider (dvs. sider der endnu ikke er fejlet ind). */ \& uffdio_register.range.start = (unsigned long) addr; uffdio_register.range.len = size; uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING; if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == \-1) err(EXIT_FAILURE, "ioctl\-UFFDIO_REGISTER"); \& /* Opret en tråd der vil behandle userfaultfd\-hændelser. */ \& s = pthread_create(&thr, NULL, fault_handler_thread, (void *) uffd); if (s != 0) { errc(EXIT_FAILURE, s, "pthread_create"); } \& /* Hovedtråden rører nu hukommelse i oversættelsen, placeringer røres 1024 byte fra hinanden. Dette vil udløse userfaultfd\-hændelser for alle sider i regionen. */ \& i = 0xf; /* Sikr at den fejlende adresse ikke er på en sidegrænse, for at teste, at vi håndterede tilfældet korrekt i fault_handling_thread(). */ while (i < size) { char c; \& c = addr[i]; printf("Read address %p in %s(): ", addr + i, __func__); printf("%c\[rs]n", c); i += 1024; usleep(100000); /* Gør tingene lidt langsommere */ } \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "SE OGSÅ" \fBfcntl\fP(2), \fBioctl\fP(2), \fBioctl_userfaultfd\fP(2), \fBmadvise\fP(2), \fBmmap\fP(2) .P \fIDocumentation/admin\-guide/mm/userfaultfd.rst\fP i Linux\-kernekildetræet .PP .SH OVERSÆTTELSE Oversættere af denne manual til dansk Joe Hansen . .PP Denne oversættelse er gratis dokumentation; læs .UR https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3 .UE eller nyere for ophavsretbetingelser. Der er INGEN ANSVAR. .PP Hvis du støder på fejl i oversættelsen af ​​denne vejledning, skal du sende en besked til .MT debian-l10n-danish@lists.debian.org .ME .