2016-05-29 16 views
2

Ist es jemals möglich, dass ein Lesevorgang auf einen Speicherort unbegrenzt verlängert wird (und ein anderer Thread den Lesevorgang nach einer beliebigen Zeitüberschreitung abschließen kann)?Kann jemals unbegrenzt auf den zugeordneten Speicher zugegriffen werden?

Zum Beispiel mit Steckdosen blockiert, können wir einen Prozess zu stoppen, erhalten bei Verwendung des read Systemaufruf:

fd = socket(AF_UNIX, SOCK_DGRAM, 0); 
read(fd, buffer, 256); 

Normalerweise können wir nicht mmap Steckdosen, aber ich möchte im Wesentlichen das Gleiche passieren wenn Zugriff auf den Speicher direkt:

int x = *(int *)map; 

ich bin von Techniken bewusst Speicherzugriff länger zu machen, wie madvise zu Seite, bevor er Zugriff auf den Speicher, aber ich bin auf der Suche nach einer Methode, dies zu bekommen dauern auf unbestimmte Zeit.

Ich habe überlegt, mmap für eine Datei zu verwenden, und dann diese Datei "sperren", konnte aber keine geeignete Schnittstelle dafür finden. Der Systemaufruf flock scheint nicht so zu funktionieren.

Speziell interessiert mich FreeBSD für x86-64-Architektur, aber Antworten für andere Unix-ähnliche Systeme wie Linux und andere Architekturen würden ebenfalls geschätzt werden.

+0

Wenn Sie den Speicherzugriff "blockieren" möchten, können Sie versuchen, eine Datei auf einem NFS-Mount zu lesen und einen echten wahlfreien Zugriff auf diesen Speicher auszuführen. – wildplasser

+0

Wenn sich die Datei auf einem benutzerdefinierten ['FUSE'-Mount] (https://en.wikipedia.org/wiki/Filesystem_in_Userspace) befindet, können Sie jedes beliebige Verhalten erhalten. –

Antwort

3

Sie könnten mprotect(..., PROT_NONE) verwenden, um die Seite, die map enthält, als nicht zugänglich zu markieren. Wenn Sie dann versuchen, darauf zuzugreifen, tritt ein Seitenfehler auf und SIGSEGV wird ausgelöst.

Sie können einen Handler für SIGSEGV installieren, der mit dem zusätzlichen Argument siginfo_t deklariert wurde. Betrachten Sie das si_addr Mitglied dieser Struktur, um zu überprüfen, ob die fehlerhafte Adresse map entspricht; Auf diese Weise können Sie Zugriffe auf diese Adresse von anderen Fehlern unterscheiden, die tatsächliche Fehler in Ihrem Code sind (z. B. NULL-Dereferenzierung). Wenn dies der Fall ist, kann der Signal-Handler warten, bis ihm gesagt wird, dass er mit dem anderen Thread fortfahren soll. Wenn Sie bereit sind, rufen Sie mprotect mit PROT_READ (oder PROT_WRITE entsprechend) und kehren Sie vom Signalhandler zurück; Die fehlerhafte Anweisung wird neu gestartet und die Ausführung wird fortgesetzt.

Dies ist ein ziemlich hässlicher Hack, und ich würde einen guten, harten Blick vorschlagen, warum Sie denken, dass Sie das tun müssen. Ihre Frage scheint wie eine XY problem sein könnte.

+0

Ich habe Ihren Vorschlag implementiert, und es funktioniert für den Benutzerlandzugriff (EG: '* (int *) buffer = 0;'), jedoch werden keine Schreibvorgänge vom Kernel eingefroren, was mein ultimatives Ziel war (EG: 'getcontext ((ucontext_t *) Puffer); '). – CHRIS

+0

@CHRIS: Kernel-Modus ist ein völlig anderes Tier. Wenn das dein Ziel wäre, hätte ich mir gewünscht, dass du es gesagt hättest. So wie es ist, sollten Sie wahrscheinlich eine neue Frage stellen. –

+0

Ich werde Ihre Antwort akzeptieren, da es für die Frage funktioniert, die ich ursprünglich beschrieben habe. Vielen Dank. – CHRIS

Verwandte Themen