GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Linux – Wie kann sichergestellt werden, dass die Speicherseiten einer gemeinsam genutzten Bibliothek von mehreren Prozessen gemeinsam genutzt werden?

Lassen Sie mich zuerst beschreiben, was ich tun möchte, gefolgt von dem, was ich tun kann, und schließlich von meinem Problem.

Ziel:Implementierung eines Flush+Flush-Cache-Angriffs in C

Ich versuche, in C den Flush+Flush-Cache-Angriff (https://gruss.cc/files/flushflush.pdf) zu implementieren. Im Grunde nutzt es die Tatsache aus, dass zwei verschiedene Prozesse möglicherweise dieselben Speicherseiten gemeinsam nutzen, wenn gemeinsam genutzte Bibliotheken verwendet werden. Dadurch ergibt sich eine „geteilte Nutzung“ des Caches.

Nehmen wir an, wir haben einen Opferprozess, der ständig läuft und manchmal eine Funktion func ausführt aus einer gemeinsam genutzten Bibliothek importiert.

Parallel dazu nehmen wir an, dass wir einen Spionageprozess haben, der auf demselben Computer läuft wie das Opfer, dessen Ziel es ist, auszuspionieren, wenn das Opfer func aufruft . Der Spion hat auch Zugriff auf dieselbe gemeinsam genutzte Bibliothek. Der Pseudocode des Spionageprozesses lautet wie folgt:

i=0;
for (i = 0; i < trace_length ; i++)
{
    trace[i] = flush_time( address of function "func");
    i++;
}

wobei flush_time( <address> ) ist eine Funktion, die die Zeit zurückgibt, die die CPU benötigt, um den Speicher zu leeren, auf den address zeigt aus allen Cache-Ebenen. Auf Intel-Prozessoren kann dies durch die Assembler-Anweisung clflush erreicht werden . Man kann beobachten, dass die Ausführung von clflush ist schneller, wenn die Adresse nicht im Cache vorhanden ist. Als Ergebnis kann das Timing, das zum Leeren einer Speicheradresse erforderlich ist, direkt übersetzt werden, ob sie im Cache vorhanden ist (oder nicht).

Der Spionageprozess gibt einen Ablaufverfolgungsvektor zurück, der die Ergebnisse von flush_time über die Zeit enthält. Aus der vorherigen Beobachtung zeigt dieser Trace höhere Timings, wenn das Opfer auch die Funktion func aufruft . Der Spion wird also abziehen, wenn das Opfer func aufruft .

Was ich schaffe:Den Angriff gegen die gemeinsam genutzte GSL-Bibliothek arbeiten zu lassen

Ich habe den oben genannten Angriff implementiert, bei dem die gemeinsam genutzte Bibliothek die GSL ist. Willkürlich habe ich gsl_stats_mean gewählt (definiert in gsl_statistics_double ), um als Funktion func zu fungieren Ich bin bereit zu spionieren.

In diesem Fall funktioniert die Spionage perfekt, da ich deutlich einen Zeitunterschied erkennen kann, wenn das Opferprogramm gsl_stats_mean aufruft

Mein Problem:Der Angriff funktioniert nicht bei einer selbst erstellten gemeinsam genutzten Bibliothek

Ich möchte jetzt meine eigene gemeinsame Bibliothek erstellen und sie für den Spion/Opfer-Test verwenden. Angenommen . bezeichnet den Ordner, in dem sich meine spy.c befindet und victim.c Dateien sind. Ich habe zwei Dateien myl.c erstellt und myl.h in einem Ordner ./src/myl , die jeweils die Beschreibung von func enthalten und es ist Erklärung. Wie zuvor ist das Ziel meines Spions, die Verwendung von func zu entdecken vom Opfer.

Beide spy.c und victim.c enthalten die Include-Zeile:

 #include "src/myl/myl.h"

Die Erstellung der gemeinsam genutzten Bibliothek erfolgt mit den folgenden Befehlen:

gcc -c -fPIC src/myl/myl.c -o bin/shared/myl.o  #creation of object in ./bin/shared
gcc -shared bin/shared/myl.o -o bin/shared/libmyl.so #creation of the shared library in ./bin/shared
gcc -c spy.c -o spy.o #creation of spy's process object file
gcc -c victim.c -o victim.o #creation of victim's process object file
gcc spy.o -Lbin/shared -lmyl -o spy #creation of spy's executable
gcc victim.o -Lbin/shared -lmyl -o victim #creation of victim's executable

Dann starte ich mein Opfer und spioniere mit den folgenden Zeilen aus:

LD_LIBRARY_PATH=$(pwd)/bin/shared ./victim
LD_LIBRARY_PATH=$(pwd)/bin/shared ./spy

Im Gegensatz zu dem Fall, in dem ich die GSL-Funktion verwendet habe, sehe ich jedoch keine Aktivität mehr auf dem Cache. Ich denke, das bedeutet, dass meine Spionage- und Opferprozesse nicht dieselbe Speicherseite für meine gemeinsam genutzte Bibliothek teilen (während dies bei Verwendung der GSL der Fall war). Beachten Sie, dass beim Kompilieren auf diese Weise das Spionieren immer noch funktioniert, wenn eine GSL-Funktion anvisiert wird.

Meine Hauptfrage lautet wie folgt:Wie kann sichergestellt werden, dass eine selbst kompilierte gemeinsam genutzte Bibliothek die Speicherauslagerung gemeinsam nutzt, wenn sie von mehreren Prozessen gleichzeitig ausgeführt wird? Es scheint bei „richtigen“ Bibliotheken, die ich installiert habe, wie GSL, gmp, native Bibliotheken usw. der Fall zu sein. Aber nicht für den, den ich selbst gemacht habe.

Vielen Dank im Voraus und ich entschuldige mich, falls die Antwort einfach ist.

EDIT:Ausgabe von LD_DEBUG=libs und files sowohl für Spion als auch für Opfer.
HINWEIS:Das Opfer heißt pg2 und Spy heißt pg1 (Entschuldigung dafür)

Zuerst libs für das Opfer, gefolgt von den Dateien für das Opfer (pg2 ). Dann libs für den Spion, gefolgt von Dateien für den Spion (pg1 ):

LD_DEBUG=libs LD_LIBRARY_PATH=$(pwd)/bin/shared ./pg2
 31714: find library=libmyl.so [0]; searching
 31714:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared/tls/x86_64:/home/romain/Documents/work/test/page_sharing/bin/shared/tls:/home/romain/Documents/work/test/page_sharing/bin/shared/x86_64:/home/romain/Documents/work/test/page_sharing/bin/shared      (LD_LIBRARY_PATH)
 31714:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/tls/x86_64/libmyl.so
 31714:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/tls/libmyl.so
 31714:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/x86_64/libmyl.so
 31714:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so
 31714: 
 31714: find library=libc.so.6 [0]; searching
 31714:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared       (LD_LIBRARY_PATH)
 31714:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libc.so.6
 31714:  search cache=/etc/ld.so.cache
 31714:   trying file=/lib/x86_64-linux-gnu/libc.so.6
 31714: 
 31714: 
 31714: calling init: /lib/x86_64-linux-gnu/libc.so.6
 31714: 
 31714: 
 31714: calling init: /home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so
 31714: 
 31714: 
 31714: initialize program: ./pg2
 31714: 
 31714: 
 31714: transferring control: ./pg2
 31714: 



LD_DEBUG=files LD_LIBRARY_PATH=$(pwd)/bin/shared ./pg2
 31901: 
 31901: file=libmyl.so [0];  needed by ./pg2 [0]
 31901: file=libmyl.so [0];  generating link map
 31901:   dynamic: 0x00007f5a3b34be48  base: 0x00007f5a3b14b000   size: 0x0000000000201028
 31901:     entry: 0x00007f5a3b14b580  phdr: 0x00007f5a3b14b040  phnum:                  7
 31901: 
 31901: 
 31901: file=libc.so.6 [0];  needed by ./pg2 [0]
 31901: file=libc.so.6 [0];  generating link map
 31901:   dynamic: 0x00007f5a3b144ba0  base: 0x00007f5a3ad81000   size: 0x00000000003c99a0
 31901:     entry: 0x00007f5a3ada1950  phdr: 0x00007f5a3ad81040  phnum:                 10
 31901: 
 31901: 
 31901: calling init: /lib/x86_64-linux-gnu/libc.so.6
 31901: 
 31901: 
 31901: calling init: /home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so
 31901: 
 31901: 
 31901: initialize program: ./pg2
 31901: 
 31901: 
 31901: transferring control: ./pg2
 31901: 


LD_DEBUG=libs LD_LIBRARY_PATH=$(pwd)/bin/shared ./pg1
 31938: find library=libmyl.so [0]; searching
 31938:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared/tls/x86_64:/home/romain/Documents/work/test/page_sharing/bin/shared/tls:/home/romain/Documents/work/test/page_sharing/bin/shared/x86_64:/home/romain/Documents/work/test/page_sharing/bin/shared      (LD_LIBRARY_PATH)
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/tls/x86_64/libmyl.so
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/tls/libmyl.so
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/x86_64/libmyl.so
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so
 31938: 
 31938: find library=libgsl.so.23 [0]; searching
 31938:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared       (LD_LIBRARY_PATH)
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libgsl.so.23
 31938:  search cache=/etc/ld.so.cache
 31938:   trying file=/usr/local/lib/libgsl.so.23
 31938: 
 31938: find library=libgslcblas.so.0 [0]; searching
 31938:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared       (LD_LIBRARY_PATH)
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libgslcblas.so.0
 31938:  search cache=/etc/ld.so.cache
 31938:   trying file=/usr/local/lib/libgslcblas.so.0
 31938: 
 31938: find library=libc.so.6 [0]; searching
 31938:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared       (LD_LIBRARY_PATH)
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libc.so.6
 31938:  search cache=/etc/ld.so.cache
 31938:   trying file=/lib/x86_64-linux-gnu/libc.so.6
 31938: 
 31938: find library=libm.so.6 [0]; searching
 31938:  search path=/home/romain/Documents/work/test/page_sharing/bin/shared       (LD_LIBRARY_PATH)
 31938:   trying file=/home/romain/Documents/work/test/page_sharing/bin/shared/libm.so.6
 31938:  search cache=/etc/ld.so.cache
 31938:   trying file=/lib/x86_64-linux-gnu/libm.so.6
 31938: 
 31938: 
 31938: calling init: /lib/x86_64-linux-gnu/libc.so.6
 31938: 
 31938: 
 31938: calling init: /lib/x86_64-linux-gnu/libm.so.6
 31938: 
 31938: 
 31938: calling init: /usr/local/lib/libgslcblas.so.0
 31938: 
 31938: 
 31938: calling init: /usr/local/lib/libgsl.so.23
 31938: 
 31938: 
 31938: calling init: /home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so
 31938: 
 31938: 
 31938: initialize program: ./pg1
 31938: 
 31938: 
 31938: transferring control: ./pg1
 31938: 
0: 322 # just some output of my spying program
1: 323 # just some output of my spying program
 31938: 
 31938: calling fini: ./pg1 [0]
 31938: 
 31938: 
 31938: calling fini: /home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so [0]
 31938: 
 31938: 
 31938: calling fini: /usr/local/lib/libgsl.so.23 [0]
 31938: 
 31938: 
 31938: calling fini: /usr/local/lib/libgslcblas.so.0 [0]
 31938: 
 31938: 
 31938: calling fini: /lib/x86_64-linux-gnu/libm.so.6 [0]
 31938: 




LD_DEBUG=files LD_LIBRARY_PATH=$(pwd)/bin/shared ./pg1
 31940: 
 31940: file=libmyl.so [0];  needed by ./pg1 [0]
 31940: file=libmyl.so [0];  generating link map
 31940:   dynamic: 0x00007fb3d8794e48  base: 0x00007fb3d8594000   size: 0x0000000000201028
 31940:     entry: 0x00007fb3d8594580  phdr: 0x00007fb3d8594040  phnum:                  7
 31940: 
 31940: 
 31940: file=libgsl.so.23 [0];  needed by ./pg1 [0]
 31940: file=libgsl.so.23 [0];  generating link map
 31940:   dynamic: 0x00007fb3d8582ac8  base: 0x00007fb3d8126000   size: 0x000000000046da60
 31940:     entry: 0x00007fb3d8180e30  phdr: 0x00007fb3d8126040  phnum:                  7
 31940: 
 31940: 
 31940: file=libgslcblas.so.0 [0];  needed by ./pg1 [0]
 31940: file=libgslcblas.so.0 [0];  generating link map
 31940:   dynamic: 0x00007fb3d8124df0  base: 0x00007fb3d7ee8000   size: 0x000000000023d050
 31940:     entry: 0x00007fb3d7eea120  phdr: 0x00007fb3d7ee8040  phnum:                  7
 31940: 
 31940: 
 31940: file=libc.so.6 [0];  needed by ./pg1 [0]
 31940: file=libc.so.6 [0];  generating link map
 31940:   dynamic: 0x00007fb3d7ee1ba0  base: 0x00007fb3d7b1e000   size: 0x00000000003c99a0
 31940:     entry: 0x00007fb3d7b3e950  phdr: 0x00007fb3d7b1e040  phnum:                 10
 31940: 
 31940: 
 31940: file=libm.so.6 [0];  needed by /usr/local/lib/libgsl.so.23 [0]
 31940: file=libm.so.6 [0];  generating link map
 31940:   dynamic: 0x00007fb3d7b1cd88  base: 0x00007fb3d7815000   size: 0x00000000003080f8
 31940:     entry: 0x00007fb3d781a600  phdr: 0x00007fb3d7815040  phnum:                  7
 31940: 
 31940: 
 31940: calling init: /lib/x86_64-linux-gnu/libc.so.6
 31940: 
 31940: 
 31940: calling init: /lib/x86_64-linux-gnu/libm.so.6
 31940: 
 31940: 
 31940: calling init: /usr/local/lib/libgslcblas.so.0
 31940: 
 31940: 
 31940: calling init: /usr/local/lib/libgsl.so.23
 31940: 
 31940: 
 31940: calling init: /home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so
 31940: 
 31940: 
 31940: initialize program: ./pg1
 31940: 
 31940: 
 31940: transferring control: ./pg1
 31940: 
0: 325 # just some output of my spying program
1: 327 # just some output of my spying program
 31940: 
 31940: calling fini: ./pg1 [0]
 31940: 
 31940: 
 31940: calling fini: /home/romain/Documents/work/test/page_sharing/bin/shared/libmyl.so [0]
 31940: 
 31940: 
 31940: calling fini: /usr/local/lib/libgsl.so.23 [0]
 31940: 
 31940: 
 31940: calling fini: /usr/local/lib/libgslcblas.so.0 [0]
 31940: 
 31940: 
 31940: calling fini: /lib/x86_64-linux-gnu/libm.so.6 [0]
 31940: 

Akzeptierte Antwort:

Da die Debug-Ausgabe von ld dynamischer Linker/Loader bestätigt, dass sowohl das victim und spy Programme die richtige Eingabedatei laden, wäre der nächste Schritt zu überprüfen, ob der Kernel tatsächlich die physikalischen Seiten eingerichtet hat, auf denen libmyl.so wird in den Speicher geladen, um zwischen dem victim geteilt zu werden und spy .

Unter Linux ist dies seit der Kernel-Version 2.6.25 über die pagemap möglich Schnittstelle im Kernel, die es Userspace-Programmen ermöglicht, die Seitentabellen und zugehörige Informationen zu untersuchen, indem Dateien in /proc gelesen werden .

Das allgemeine Verfahren zur Verwendung von Pagemap, um herauszufinden, ob sich zwei Prozesse Speicher teilen, sieht folgendermaßen aus:

  1. Lies/proc/<pid>/maps für beide Prozesse, um zu bestimmen, welche Teile des Speicherplatzes auf welche Objekte abgebildet werden.
  2. Wählen Sie die Karten aus, die Sie interessieren, in diesem Fall die Seiten, zu denen libmyl.so gehört zugeordnet ist.
  3. Öffnen Sie /proc/<pid>/pagemap . Die pagemap besteht aus 64-Bit-Pagemap-Deskriptoren, einer pro Seite. Die Zuordnung zwischen der Adresse der Seite und ihrer Deskriptoradresse in der pagemap ist Seitenadresse / Seitengröße * Deskriptorgröße . Suchen Sie nach den Deskriptoren der Seiten, die Sie untersuchen möchten.
  4. Lesen Sie einen 64-Bit-Deskriptor als Ganzzahl ohne Vorzeichen für jede Seite aus der pagemap .
  5. Vergleichen Sie die Seitenrahmennummer (PFN) in den Bits 0-54 des Seitendeskriptors zwischen libmyl.so Seiten für victim und spy . Wenn die PFNs übereinstimmen, teilen sich die beiden Prozesse dieselben physischen Seiten.
Verwandte:Windows – Wie konnte Windows das Linux-Dateisystem NICHT beschädigen, wenn es Partitionsschemata durcheinander brachte?

Der folgende Beispielcode veranschaulicht, wie die pagemap können innerhalb des Prozesses aufgerufen und ausgedruckt werden. Es verwendet dl_iterate_phdr() um die virtuelle Adresse jeder gemeinsam genutzten Bibliothek zu bestimmen, die in den Speicherbereich des Prozesses geladen wird, sucht dann nach und druckt die entsprechende pagemap aus /proc/<pid>/pagemap .

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <link.h>
#include <errno.h>
#include <error.h>

#define E_CANNOT_OPEN_PAGEMAP 1
#define E_CANNOT_READ_PAGEMAP 2

typedef struct __attribute__ ((__packed__)) {
    union {
        uint64_t pmd;
        uint64_t page_frame_number : 55;
        struct {
            uint64_t swap_type: 5;
            uint64_t swap_offset: 50;
            uint64_t soft_dirty: 1;
            uint64_t exclusive: 1;
            uint64_t zero: 4;
            uint64_t file_page: 1;
            uint64_t swapped: 1;
            uint64_t present: 1;
        };
    };
} pmd_t;


static int print_pagemap_for_phdr(struct dl_phdr_info *info,
                                  size_t size, void *data)
{
    struct stat statbuf;

    size_t pagesize = sysconf(_SC_PAGESIZE);

    char pagemap_path[BUFSIZ];
    int pagemap;

    uint64_t start_addr, end_addr;

    if (!strcmp(info->dlpi_name, "")) {
        return 0;
    }

    stat(info->dlpi_name, &statbuf);

    start_addr = info->dlpi_addr;
    end_addr = (info->dlpi_addr + statbuf.st_size + pagesize) & ~(pagesize-1);

     printf("n%10p-%10p %snn",
            (void *)start_addr,
            (void *)end_addr,
            info->dlpi_name);

     snprintf(pagemap_path, sizeof pagemap_path, "/proc/%d/pagemap", getpid());

     if ((pagemap = open(pagemap_path, O_RDONLY)) < 0) {
         error(E_CANNOT_OPEN_PAGEMAP, errno, 
               "cannot open pagemap: %s", pagemap_path);
     }

     printf("%10s %8s %7s %5s %8s %7s %7sn",
            "", "", "soft-", "", "file /", "", "");
     printf("%10s %8s %7s %5s %11s %7s %7sn",
            "address", "pfn", "dirty", "excl.",
            "shared anon", "swapped", "present");

     for (unsigned long i = start_addr; i < end_addr; i += pagesize) {
          pmd_t pmd;

          if (pread(pagemap, &pmd.pmd, sizeof pmd.pmd, (i / pagesize) * sizeof pmd) != sizeof pmd) {
              error(E_CANNOT_READ_PAGEMAP, errno,
                    "cannot read pagemap: %s", pagemap_path);
          }

          if (pmd.pmd != 0) {
              printf("0x%10" PRIx64 " %06" PRIx64 " %3d %5d %8d %9d %7dn", i,
                     (unsigned long)pmd.page_frame_number,
                     pmd.soft_dirty,
                     pmd.exclusive,
                     pmd.file_page,
                     pmd.swapped,
                     pmd.present);
          }
    }

    close(pagemap);

    return 0;
}

int main()
{
    dl_iterate_phdr(print_pagemap_for_phdr, NULL);

    exit(EXIT_SUCCESS);
}

Die Ausgabe des Programms sollte ungefähr so ​​aussehen:

$ sudo ./a.out

0x7f935408d000-0x7f9354256000 /lib/x86_64-linux-gnu/libc.so.6

                      soft-         file /                
   address      pfn   dirty excl. shared anon swapped present
0x7f935408d000 424416   1     0        1         0       1
0x7f935408e000 424417   1     0        1         0       1
0x7f935408f000 422878   1     0        1         0       1
0x7f9354090000 422879   1     0        1         0       1
0x7f9354091000 43e879   1     0        1         0       1
0x7f9354092000 43e87a   1     0        1         0       1
0x7f9354093000 424790   1     0        1         0       1
...

wo:

  • address ist die virtuelle Adresse der Seite
  • pfn ist die Seitennummer der Seite
  • soft-dirty gibt an, ob das Soft-Dirty-Bit im Page Table Entry (PTE) der Seite gesetzt ist.
  • excl. gibt an, ob die Seite exklusiv gemappt ist (d. h. die Seite wird nur für diesen Prozess gemappt).
  • file / shared anon gibt an, ob es sich bei der Seite um eine Dateiseite oder eine gemeinsam genutzte anonyme Seite handelt.
  • swapped gibt an, ob die Seite gerade ausgetauscht wird (impliziert present ist null).
  • present gibt an, ob die Seite derzeit im residenten Satz des Prozesses vorhanden ist (impliziert swapped ist null).
Verwandte:grundlegende Linux (1) Spickzettel

(Hinweis:Ich führe das Beispielprogramm mit sudo aus wie seit Linux 4.0 nur Benutzer mit dem CAP_SYS_ADMIN Fähigkeit kann PFNs von /proc/<pid>/pagemap erhalten . Ab Linux 4.2 wird das PFN-Feld auf Null gesetzt, wenn der Benutzer CAP_SYS_ADMIN nicht hat . Der Grund für diese Änderung besteht darin, es schwieriger zu machen, eine andere speicherbezogene Schwachstelle, den Rowhammer-Angriff, auszunutzen, indem die Informationen über die von den PFNs offengelegte Zuordnung von virtuell zu physisch verwendet werden.)

Wenn Sie das Beispielprogramm mehrmals ausführen, sollten Sie feststellen, dass sich die virtuelle Adresse der Seite ändern sollte (aufgrund von ASLR), aber die PFN für gemeinsam genutzte Bibliotheken, die von anderen Prozessen verwendet werden, gleich bleiben sollte.

Wenn die PFNs für libmyl.so Übereinstimmung zwischen dem victim und spy Programm, würde ich anfangen, nach einem Grund dafür zu suchen, warum der Angriff im Angriffscode selbst fehlschlägt. Wenn die PFNs nicht übereinstimmen, können die zusätzlichen Bits einen Hinweis darauf geben, warum die Seiten nicht für die gemeinsame Nutzung eingerichtet sind. Die pagemap Bits geben Folgendes an:

present file exclusive state:
   0      0     0      non-present
   1      1     0      file page mapped somewhere else
   1      1     1      file page mapped only here
   1      0     0      anonymous non-copy-on-write page (shared with parent/child)
   1      0     1      anonymous copy-on-write page (or never forked)

Copy-on-Write-Seiten in (MAP_FILE | MAP_PRIVATE) Bereiche sind in diesem Zusammenhang anonym.

Bonus: Um die Anzahl zu erhalten eine Seite zugeordnet wurde, kann das PFN verwendet werden, um die Seite in /proc/kpagecount nachzuschlagen . Diese Datei enthält eine 64-Bit-Zählung der Anzahl der Zuordnungen jeder Seite, indiziert durch PFN.


Linux
  1. So initialisieren Sie eine gemeinsam genutzte Bibliothek unter Linux

  2. Wie kann ich die Liste der Funktionen anzeigen, die eine gemeinsam genutzte Linux-Bibliothek exportiert?

  3. Wie listet man Prozesse auf, die an ein Shared-Memory-Segment in Linux angehängt sind?

  4. So verwenden Sie Shared Memory mit Linux in C

  5. Wie wird die Versionierung einer gemeinsam genutzten Bibliothek unter Linux durchgeführt?

So überprüfen Sie den gemeinsam genutzten Linux-Speicher mit dem ipcs-Befehl

So installieren Sie die Ncurses-Bibliothek unter Linux

So löschen Sie den Auslagerungsspeicher unter Linux

So löschen Sie den Speichercache in Linux

So finden Sie die am häufigsten ausgeführten Prozesse nach Speicher- und CPU-Auslastung in Linux

Wie wirkt sich ein Single-Bit-Speicherfehler auf Linux aus?