Przede wszystkim chciałbym powiedzieć, to powinien służyć jako dobry argument, aby nie używać niepotrzebnie jako "odczytu zoptymalizowanego" lub podobnego. Oprócz usuwania urządzeń, problemy takie jak obcięcie plików przez inne procesy mogą powodować dostęp do błędów z SIGBUS
.
Jeśli naprawdę potrzebujesz użyć mmap
, możesz zainstalować procedurę obsługi sygnału dla SIGBUS
. Jej zadanie powinno w zasadzie być:
- Ustaw globalny (lub wątku lokalnego, jeśli program jest wielowątkowy) Flaga że wystąpił
SIGBUS
, więc kod powodujący błąd może być świadomy.
- Zadzwoń pod
mmap
z MAP_FIXED
, aby zmapować nową anonimową stronę na górze strony z błędami. Opcjonalnie wypełnij go danymi, które będą rozpoznane przez kod dostępu do mapy jako błędny; to może uczynić krok 1 niepotrzebnym.
Alternatywnym rozwiązaniem byłoby ustawienie globalne (lub wątku lokalnego) jmp_buf
przed uzyskaniem dostępu do mapy, i procedura obsługi sygnału wystarczy zadzwonić longjmp
.
Zauważ, że ani mmap
ani longjmp
jest asynchroniczny sygnał bezpieczny, ale SIGBUS
w pytaniu nie jest to sygnał asynchroniczny (choć powinno to być może być uważana za jedną jeśli dostęp faulting się wewnątrz biblioteki non-async-signal-safe funkcja taka jak sscanf
). Dopóki jest to twój własny kod, a nie funkcje biblioteczne, dostęp do mapy, powinieneś być bezpieczny. I mmap
jest bezpieczny pod względem asynchronicznym w większości/we wszystkich implementacjach w świecie rzeczywistym, więc powinieneś być w porządku z pierwszym rozwiązaniem w praktyce, nawet jeśli nie jest ono formalnie poprawne.
Nie sądzę, że jest to bardzo pomocne ze względu na możliwe warunki wyścigu. Czy pomogłoby oczekiwać i złapać 'SIGBUS' wokół kodu uzyskującego dostęp do odwzorowanego regionu? Lub coś podobnego? –
Nie. "SIGBUS" niekoniecznie jest możliwy do odzyskania, chociaż niektóre implementacje ponawiają instrukcję błędną po powrocie z programu obsługi. –
@SimonRichter Nie musisz ponawiać instrukcji błędu, musisz jedynie ustalić, że nie możesz kontynuować odczytu/zapisu, po czym przestajesz próbować uzyskać dostęp do regionu i powrócić do osoby dzwoniącej z pewnym wskaźnikiem błędu. Być może 'setjmp()'/'longjmp()' byłby w stanie uniknąć ponownego wykonania instrukcji błędu. –