2012-10-15 11 views

Odpowiedz

-1

Nie można uzyskać dostępu do pliku, który nie jest dostępny. Sprawdź, czy plik nadal istnieje, lub użyj pliku, którego nie można odmontować.

+4

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? –

+1

Nie. "SIGBUS" niekoniecznie jest możliwy do odzyskania, chociaż niektóre implementacje ponawiają instrukcję błędną po powrocie z programu obsługi. –

+0

@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. –

2

Najprostszą rzeczą jest skonfigurowanie programu obsługi sygnału, który będzie sprawdzać dostęp do lokalizacji pamięci, które odpowiadają adresom ed z mmap.

Można by użyć formularza sigaction z obsługi sygnałów, zamiast prostszych signal ładowarki teleskopowe jako sigaction otrzymywać informacje w parametrze struct __siginfo * odpowiadającym adresem sygnału. Można to sprawdzić, aby sprawdzić, czy znajduje się w zakresie adresów pliku mmap ed.

mmap jest świetny, gdy nie chcesz radzić sobie z komplikacjami odczytu/zapisu danych w buforze, ale dostajesz tylko jedną formę błędu (sygnał) z powodu awarii. z mechanizmem read/write, można uzyskać errno i ustalić, co się stało. W tym przypadku jest to bardzo duży wybór deweloperów.

Aby przejść do lokalizacji po odebraniu sygnału następnie trzeba będzie skorzystać z setjmp i longjmp/siglongjmp - patrz pewne zastosowanie tego w this question

6

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ć:

  1. 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.
  2. 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.

+2

Wyrażałoby to w ten sposób: więcej jest do 'mmap' niż na pierwszy rzut oka - ponieważ obsługa błędów jest znacznie bardziej skomplikowana niż w przypadku tradycyjnych operacji we/wy. To niekoniecznie jest powód, aby używać '' mmap' ... po prostu bądź świadomy duchów, które przywołujesz ;-) –

+0

Upewnij się, że nie wylecą Ci z nosa .. :-) –

-1

Możesz otrzymać powiadomienie o każdej zmianie w pliku (ach), katalogu (ach) przy użyciu http://linux.die.net/man/7/inotify. możesz rozważyć użycie IN_DELETE.

+3

Czy te powiadomienia będą natychmiastowe jako błędy strony, które OP próbuje ograniczyć? Jeśli nie, nie przejmuj się. –

+0

Wygląda na to, że musisz wywołać 'read()', aby sprawdzić, czy nastąpiły jakieś zmiany, ale zmiany mogą nastąpić między 'read()' zwracającym nic interesującego i następującym dostępem do pamięci. To jest wyścigowy stan. Ponadto kolejka zdarzeń może być przepełniona. To nie jest rozwiązanie. –

Powiązane problemy