Załóżmy, że czytam (cat) plik, gdy inny proces przepisuje jego zawartość. Czy wynik jest przewidywalny? Co by się stało?
Załóżmy, że czytam (cat) plik, gdy inny proces przepisuje jego zawartość. Czy wynik jest przewidywalny? Co by się stało?
Odpowiedzi:
To zależy od tego, co robi pisarz.
Jeśli program piszący zastąpi istniejący plik, czytelnik zobaczy nową treść, gdy program piszący przejmie czytnik, jeśli w ogóle. Jeśli pisarz i czytelnik działają ze zmienną prędkością, czytelnik może naprzemiennie wyświetlać starą i nową treść.
Jeśli program piszący przycina plik, zanim zacznie zapisywać, czytnik uruchomi się na końcu pliku w tym momencie.
Jeśli program piszący utworzy nowy plik, a następnie przeniesie nowy plik do starej nazwy, czytnik będzie kontynuował czytanie ze starego pliku. Jeśli otwarty plik zostanie przeniesiony lub usunięty, procesy, które go otworzyły, kontynuują czytanie z tego samego pliku. Jeśli plik zostanie usunięty, faktycznie pozostaje na dysku (ale nie ma możliwości jego ponownego otwarcia), dopóki ostatni proces go nie zamknie.
Systemy uniksowe zwykle nie mają obowiązkowych blokad . Jeśli aplikacja chce się upewnić, że komponent piszący i komponent czytający nie nadepną na siebie, programista musi zastosować odpowiednie blokowanie. Istnieje kilka wyjątków, w których plik otwarty przez jądro może być chroniony przed zapisem przez aplikacje użytkownika, na przykład obraz systemu plików w pętli lub plik wykonywalny wykonywany w niektórych wariantach unixa.
ftp
/ sftp
Powiedzmy, że proces rozpoczyna odczyt przesłanego ftp
pliku, gdy inna wersja tego samego pliku zastępuje go z powodu nowej transmisji.
Jest to klasyczny warunek wyścigu, więc wynik jest z definicji nieprzewidywalny.
Między innymi zależy to od
fopen(3)
lub open(2)
tryby zapisu,Jeśli musisz być w stanie odczytać plik podczas jego przepisywania, możesz zmusić program piszący do utworzenia przejściowej kopii pliku, zmodyfikować go, a następnie skopiować z powrotem do oryginalnego pliku. Tak to rsync
robi na przykład. Istnieje wiele sposobów realizacji tego, ale nie ma darmowego lunchu. Każda metoda ma swoje własne wady i konsekwencje.
Poprzedni respondenci mieli bardziej wyczerpujące wyjaśnienia niż to, ale oto sztuczka, która na pewno działa również, robiąc dokładnie to, czego chce:
$ tail -f <filename>
Pokaże koniec pliku podczas jego zapisywania. Przydaje się, jeśli chcesz potokować STDERR do pliku, ale nadal widzisz go na przykład w innym oknie terminala.