2013-07-02 19 views
10

Co by się stało, gdyby zadzwonić pod numer read (lub write lub oba) w dwóch różnych wątkach, na tym samym deskryptorze pliku (pozwala nam to powiedzieć, że interesuje nas plik lokalny, a jest to plik deskryptor pliku gniazda), bez użycia jawnie mechanizmu synchronizacji?C odczyt i bezpieczeństwo wątków (linux)

Odczyt i zapis są syscall, więc na jednordzeniowym procesorze prawdopodobnie jest to pech, że dwa odczyty będą wykonywane "w tym samym czasie". Ale z wieloma rdzeniami ...

Co zrobi jądro Linux?

I bądźmy trochę bardziej ogólni: czy zachowanie jest zawsze takie samo dla innych jąder (np. BSD)?

Edycja: Zgodnie z close documentation, powinniśmy być pewni, że deskryptor pliku nie jest używany przez syscall w innym wątku. Tak więc szwy wymagałyby jawnej synchronizacji przed zamknięciem deskryptora pliku (a więc również wokół odczytu/zapisu, jeśli wątek, który może go wywoływać, nadal działa).

+2

Nie można użyć mechanizmu synchronizacji; jądro już to robi dla ciebie. –

+0

Mam na myśli, używając jawnie. Więc jądro wykonuje całą pracę według własnego, a czytanie/pisanie/wywoływanie obu na nich nie wymaga żadnej jawnej synchronizacji? –

+0

O ile mi wiadomo, tak. Nie jestem ekspertem od jądra Linuksa, ale nie mogę sobie wyobrazić, że jest inaczej. Może przyjdzie ktoś z bardziej szczegółową wiedzą. –

Odpowiedz

11

Dowolny dostęp do deskryptorów plików na poziomie systemu (systemowa) jest bezpieczny dla wszystkich popularnych systemów UNIX. Chociaż w zależności od wieku niekoniecznie są one bezpieczne.

Jeśli wywołasz read, write, accept lub podobny na deskryptorze pliku z dwóch różnych zadań, wówczas wewnętrzny mechanizm blokujący jądra rozwiąże rywalizację.

Dla odczytów każdy bajt może być odczytany tylko raz, a zapisy zostaną wykonane w dowolnej niezdefiniowanej kolejności.

Funkcje biblioteki stdio: fread, fwrite i co. mają również domyślnie wewnętrzne blokowanie na strukturach sterujących, chociaż za pomocą flag można to wyłączyć.

+1

Witaj. Czy możesz zamieścić oficjalną dokumentację, która oznaczy te funkcje jako bezpieczne dla wątków. – felknight

+1

Byłbym bardzo szczęśliwy, gdybyś mógł dodać linki do oficjalnej dokumentacji zarówno do odczytu/zapisu/akceptacji, jak i fread/fwrite :) –

+0

Jestem prawie pewny, że glibc nie będzie bezpieczny dla wątków na fread, fwrite, chyba że połączysz się z libpthread . Ale oczywiście jeśli używasz wątków, to już powinno być prawdą. –

0

Wynik będzie zależał od tego, w jaki sposób wątki mają być uruchamiane w danym momencie.

Jednym ze sposobów uniknięcia niezdefiniowanego zachowania przy wielowątkowości jest założenie, że wykonujesz operacje pamięciowe. Na przykład. aktualizowanie połączonej listy lub zmiana zmiennej, itp.

Jeśli używasz mutex/semaforów/blokady lub innego mechanizmu synchronizacji, powinien działać zgodnie z przeznaczeniem.

2

Komentarz na temat zamknięcia jest taki, że zamykanie deskryptora plików w sytuacji, w której inny wątek może próbować go użyć, nie ma większego sensu. Tak więc, chociaż jest to "bezpieczne" w odniesieniu do jądra, może prowadzić do dziwnych, trudnych do zdiagnozowania przypadków narożnych.

Jeśli wątek zamyka deskryptor pliku, podczas gdy drugi wątek próbuje go odczytać, drugi wątek może otrzymać nieoczekiwany błąd EBADF. Co gorsze, jeśli trzeci wątek otwiera jednocześnie nowy plik, który może ponownie przydzielić ten sam plik fd, a drugi wątek może przypadkowo odczytać z nowego pliku, a nie ten, którego oczekiwał ...

1

Dbaj o ci, którzy podążają w twoich śladach

To zupełnie normalne, aby chronić deskryptor pliku za pomocą semafora mutex. Usuwa wszelką zależność od zachowania jądra, więc granice wiadomości są teraz pewne.Nie musisz wtedy cytować ostatniego akapitu na dole strony z numerem 1539, co tłumaczy, dlaczego muteks nie jest konieczny (przesadziłem, ale dostaję moje znaczenie)

To również wyjaśnia każdemu, kto czyta twój kod, w którym deskryptor pliku jest używany przez więcej niż jeden wątek.

Fringe Benefit

Jest korzyść frędzle do korzystania mutex ten sposób. Załóżmy, że masz różne wiadomości pochodzące z różnych wątków, a niektóre z nich są ważniejsze niż inne. Wszystko, co musisz zrobić, to ustawić priorytety wątków, aby odzwierciedlić ich ważność. W ten sposób system operacyjny zapewni, że twoje wiadomości będą wysyłane w kolejności ważności, przy minimalnym wysiłku ze strony użytkownika.

Powiązane problemy