Forum Coders' city Strona Główna Coders' city
Nasza pasja to programowanie!
 

 PomocPomoc   SzukajSzukaj   UżytkownicyUżytkownicy   GrupyGrupy  RejestracjaRejestracja 
Archiwum starego forum + teoria    RSS & Panel/SideBar
 ProfilProfil   Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości   ZalogujZaloguj 

Potrzebuję szybkiej odpowiedzi na moje pytanie... Zasady

Linux: zamykanie plików w C i C++



 
Odpowiedz do tematu    Forum Coders' city Strona Główna -> Biblioteki
Zobacz poprzedni temat :: Zobacz następny temat  
Autor Wiadomość
atlantis86



Dołączył: 22 Kwi 2014
Posty: 12

PostWysłany: Pią Kwi 08, 2016 8:05 am  OP    Temat postu: Linux: zamykanie plików w C i C++ Odpowiedz z cytatem Pisownia

Przepraszam za pytanie, które większości może się wydać banalne, ale do tej pory programowałem głównie mikrokontrolery (AVR, PIC32, w niewielkim stopniu Arduino) i od jakiegoś czasu, bardzo powoli przenoszę się na Linuksa (Raspberry Pi).
Jedna rzecz nie daje mi spokoju, bo w cudzych przykładach widzę bardzo różne podejścia.
A mianowicie co się dzieje z otwartymi deskryptorami plików, gdy proces zostanie zakończony?

1) Rozważmy na przykład sytuację, kiedy mam otwarty jakiś plik, a potem wywołuję funkcję fork(). Tworzy się proces potomny, który przejmuje deskryptory. Następnie zamykam proces "rodzica", np. tworząc daemona. Co się stanie z otwartym plikiem, gdy również proces potomny zostanie zakończony? System zorientuje się, że nikt go nie używa i sam posprząta, czy też dany deskryptor wyleci z puli do kolejnego restartu?
2) Czy w związku z powyższym powinienem napisać funkcje przejmujące wszystkie możliwe sygnały kończące proces, sprawdzać w nich czy pliki są otwarte, a jeśli tak - zamykać je? Co w przypadku sygnału SIGKILL, którego nie da się przechwycić?
3) Jeśli proces zostaje nagle zamknięty, co się dzieje z otwartymi socketami sieciowymi, sesjami sysloga czy plikami obsługiwanymi przez standardową bibliotekę C (FILE*)? System po nich posprząta, czy taka sytuacja może mieć jakieś negatywne następstwa? Czy też może jedynym skutkiem takiego zdarzenia będzie utrata danych z bufora, które jeszcze nie zdążyły trafić na dysk?
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an
Site Admin


Dołączył: 26 Maj 2005
Posty: 18787

PostWysłany: Pią Kwi 08, 2016 11:17 am      Temat postu: Re: Linux: zamykanie plików w C i C++ Odpowiedz z cytatem Pisownia

atlantis86 napisał:
Rozważmy na przykład sytuację, kiedy mam otwarty jakiś plik, a potem wywołuję funkcję fork(). Tworzy się proces potomny, który przejmuje deskryptory. Następnie zamykam proces "rodzica", np. tworząc daemona. Co się stanie z otwartym plikiem, gdy również proces potomny zostanie zakończony? System zorientuje się, że nikt go nie używa i sam posprząta, czy też dany deskryptor wyleci z puli do kolejnego restartu?
W Linuksie deskryptory są przypisane do procesów. Jeśli proces się kończy, deskryptor jest zwalniany.

atlantis86 napisał:
2) Czy w związku z powyższym powinienem napisać funkcje przejmujące wszystkie możliwe sygnały kończące proces, sprawdzać w nich czy pliki są otwarte, a jeśli tak - zamykać je? Co w przypadku sygnału SIGKILL, którego nie da się przechwycić?
SIGKILL jest sygnałem bezwarunkowego zabicia procesu i w przypadku jego użycia nikt nie przejmuje się zasobami - z założenia. W przypadku pozostałych sygnałów program i tak musi wrócić* do normalnego kodu i to dopiero on może zamknąć proces, więc wszelkie procedury związane ze zwolnieniem zasobów zostaną wykonane (zakładając prawidłowe napisanie programu).

atlantis86 napisał:
Jeśli proces zostaje nagle zamknięty, co się dzieje z otwartymi socketami sieciowymi, sesjami sysloga czy plikami obsługiwanymi przez standardową bibliotekę C (FILE*)?
W Linuksie wszystkie trzy oparte są o deskryptory, więc deskryptory są zwalniane. Natomiast stan powiązanych z deskryptorami zasobów jest niezdefiniowany, więc np. do pliku lub drugiej strony połączenia może trafić tylko część danych etc.
____
* Chyba że masz zamiar zabić swój proces wywołaniem abort, które rzuci SIGFAULTa - to jedyna metoda zamknięcia procesu z poziomu procedury obsługi sygnału z użyciem standardowych funkcji.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
atlantis86



Dołączył: 22 Kwi 2014
Posty: 12

PostWysłany: Pią Kwi 08, 2016 11:26 am  OP    Temat postu: Re: Linux: zamykanie plików w C i C++ Odpowiedz z cytatem Pisownia

marcin_an napisał:
W Linuksie deskryptory są przypisane do procesów. Jeśli proces się kończy, deskryptor jest zwalniany.


Czyli zasada ta nie obowiązuje, jeśli działają jakieś procesy potomne, które przejęły deskryptory plików od swojego rodzica i jeśli same wywołają fork(), przekażą je dalej. Deskryptor wraca do puli wartości przeznaczonych do ponownego wykorzystania dopiero po zamknięciu ostatniego procesu potomnego, dobrze to rozumiem?
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an
Site Admin


Dołączył: 26 Maj 2005
Posty: 18787

PostWysłany: Pią Kwi 08, 2016 12:06 pm      Temat postu: Odpowiedz z cytatem Pisownia

Nie, deskryptor jest zawsze przypisany do jednego procesu. Procesy potomne mają swoje własne. W momencie zakończenia fork mają one te same numery, ale nie są powiązane z deskryptorami procesu-rodzica, a same numery mogą zostać zwielokrotnione, w tym zmienione, dupami. Natomiast jeden zasób może mieć wiele deskryptorów odnoszacych się do niego. I w ten sposób wiele procesów, swoimi deskryptorami, trzyma jeden plik. Gdy wszystkie procesy zwolnią wszystkie deskryptory, zasób jest "wolny" i system może go usunąć.

Przy czym zauważ, że mówimy w tym momencie o zasobie w postaci np. otwartego pliku. Bo sam plik, jako zbiór danych na dysku, może mieć jeszcze dodatkowo odniesienia z systemu plików (dowiązania). Czyli o ile system zamknie wejście-wyjście na takim pliku, to sam plik nie zostanie usunięty do momentu aż również system plików odlinkuje wszystkie dowiązania. Jeśli utworzysz sobie tymczasowy plik i nie odlinkujesz z systemu plików, a proces oberwie SIGKILL-em, to owy plik zostanie na dysku - nie jesteś w stanie nic na to poradzić.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
Garf



Dołączył: 25 Maj 2005
Posty: 3585
Skąd: Rzeszów

PostWysłany: Pią Kwi 08, 2016 1:02 pm      Temat postu: Odpowiedz z cytatem Pisownia

marcin_an napisał:
mogą zostać zwielokrotnione, w tym zmienione, dupami.
Gdybym nie wiedział że chodzi o duplikaty... :D

</offtopic>

_________________
Internet nadal „nic nie rozumie”, żadnego odkrycia, choćby od niego zależał los świata,
ale nadanego w egzotycznym języku, nie odróżni od nieco mniej ważnej wieści,
że u ciotki w placku z jabłkami zrobił się w piekarniku zakalec.
Stanisław Lem
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an
Site Admin


Dołączył: 26 Maj 2005
Posty: 18787

PostWysłany: Pią Kwi 08, 2016 4:48 pm      Temat postu: Odpowiedz z cytatem Pisownia

Garf:
Nie bez powodu zawsze tak to wyrażam. Za starych, studenckich czasów z Taerilem mieliśmy wykład z POSIXa i prowadząca zapytała się, o czym na poprzednim wykładzie była mowa. Na co T. bez wahania wypalił: "o dupach" :).

atlantis86:
Co do obsługi sygnałów i zwalniania zasobów, to zauważ, że sygnały w żaden sposób nie kolidują z normalnym działaniem programu (przykład: prosta implementacja tee w C):
Kod:
#include <stdbool.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

static sig_atomic_t stop = false;

static void handleExitSig(int sig) {
    stop = true;
}

int main(int argc, char** argv) {
    static size_t const bufferCapacity = 8388608ul;
    bool status = true;
    char const* outputName;
    int outputFd;
    bool closeOutput;
    char* buffer;
    
    signal(SIGTERM, handleExitSig);
    signal(SIGQUIT, handleExitSig);
    
    if (NULL != argv[1]) {
        outputName = argv[1];
    } else {
        outputName = "-";
    }
    
    if (0 == strcmp("-", outputName)) {
        outputFd = STDOUT_FILENO;
        closeOutput = false;
    } else {
        outputFd = open(outputName,
              O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
        if (outputFd < 0) {
            perror("open");
            status = false
            closeOutput = false;
        } else {
            closeOutput = true;
        }
    }
    
    buffer = calloc(1, bufferCapacity);
    if (NULL == buffer) {
        perror("calloc");
        status = false;
    }
    
    while (status && !stop) {
        ssize_t bytesInBuffer = read(STDIN_FILENO, buffer, bufferCapacity);
        size_t bufferOffset = 0;
        if (0 == bytesInBuffer) {
            stop = true;
        } else if (bytesInBuffer < 0 && !stop) {
            perror("read");
            status = false;
        }
        
        while (status && !stop && bytesInBuffer > 0) {
            ssize_t bytesWritten = write(outputFd,
                  buffer + bufferOffset, bytesInBuffer);
            if (bytesWritten < 0 && !stop) {
                perror("write");
                status = false;
            } else {
                if (STDOUT_FILENO != outputFd) {
                    write(STDOUT_FILENO, buffer + bufferOffset, bytesInBuffer);
                }
                bytesInBuffer -= bytesWritten;
                bufferOffset += bytesWritten;
            }
            
        }
    }
    
    free(buffer);
    if (closeOutput) {
        if (0 != close(outputFd)) {
            perror("close");
        }
    }
    
    return status? EXIT_SUCCESS : EXIT_FAILURE;
}

Jeżeli chcesz sprawdzić, co dzieje się z deskryptorami "pod spodem" w twoim programie, rzuć okiem na lsof oraz zawartość /proc/PID/fd i /proc/PID/fdinfo.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
Wyświetl posty z ostatnich:   
Odpowiedz do tematu    Forum Coders' city Strona Główna -> Biblioteki Wszystkie czasy w strefie CET (Europa)

Strona 1 z 1

 
Skocz do:  
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Możesz dodawać załączniki na tym forum
Możesz pobierać pliki z tego forum




Debug: strone wygenerowano w 0.02880 sekund, zapytan = 11
contact

| Darmowe programy i porady Jelcyna | Tansze zakupy w Helionie | MS Office Blog |