W errno.h
, ta zmienna jest zadeklarowana jako, extern int errno;
więc moje pytanie brzmi, czy bezpiecznie jest sprawdzić errno
wartość po niektórych wywołaniach lub użyć perror () w kodzie wielowątkowym. Czy to zmienna bezpieczna dla wątków? Jeśli nie, to jaka jest alternatywa?
Używam Linuksa z GCC na architekturze x86.
c
linux
multithreading
gcc
vinit dhatrak
źródło
źródło
Odpowiedzi:
Tak, jest bezpieczny dla wątków. W systemie Linux globalna zmienna errno jest specyficzna dla wątku. POSIX wymaga, aby errno było bezpieczne dla wątków.
Zobacz http://www.unix.org/whitepapers/reentrant.html
Zobacz także http://linux.die.net/man/3/errno
źródło
# if !defined _LIBC || defined _LIBC_REENTRANT
, _LIBC nie jest zdefiniowane podczas kompilacji normalnych programów. W każdym razie uruchom echo#include <errno.h>' | gcc -E -dM -xc -
i spójrz na różnicę zi bez -pthread. errno jest#define errno (*__errno_location ())
w obu przypadkach.tak
Errno nie jest już prostą zmienną, jest czymś złożonym za kulisami, szczególnie w celu zapewnienia bezpieczeństwa wątków.
Zobacz
$ man 3 errno
:Możemy dwukrotnie sprawdzić:
źródło
Oto, co mówi standard C:
Ogólnie
errno
jest to makro, które wywołuje funkcję zwracającą adres numeru błędu dla bieżącego wątku, a następnie wyłuskuje go.Oto co mam w Linuksie, w /usr/include/bits/errno.h:
W końcu generuje taki kod:
źródło
W wielu systemach uniksowych kompilowanie z
-D_REENTRANT
zapewnia, żeerrno
jest to bezpieczne wątkowo.Na przykład:
źródło
-D_REENTRANT
. Zapoznaj się z dyskusją na temat innej odpowiedzi na to samo pytanie.-D_XOPEN_SOURCE=500
lub-D_XOPEN_SOURCE=600
. Nie każdy zadaje sobie trud, aby upewnić się, że zostało określone środowisko POSIX - a potem-D_REENTRANT
może uratować twój boczek. Ale nadal musisz uważać - na każdej platformie - aby uzyskać pożądane zachowanie.errno
który rozwija się do modyfikowalnej lwartości (201), która ma typint
i czas trwania lokalnego przechowywania wątku, której wartość jest ustawiana na dodatnią liczbę błędów przez kilka funkcji bibliotecznych. Jeśli definicja makra jest blokowana w celu uzyskania dostępu do rzeczywistego obiektu lub program definiuje identyfikator z nazwąerrno
, zachowanie jest niezdefiniowane. [... ciąg dalszy ...]errno
nie musi być identyfikatorem obiektu. Może się rozwinąć do modyfikowalnej lwartości wynikającej z wywołania funkcji (na przykład*errno()
). Główny tekst kontynuuje: Wartość errno w początkowym wątku wynosi zero podczas uruchamiania programu (początkowa wartość errno w innych wątkach jest wartością nieokreśloną), ale nigdy nie jest zerowana przez żadną funkcję biblioteczną. POSIX używa standardu C99, który nie rozpoznaje wątków. [… także ciąg dalszy…]To jest z
<sys/errno.h>
mojego Maca:Więc
errno
jest teraz funkcją__error()
. Funkcja jest zaimplementowana tak, aby była bezpieczna dla wątków.źródło
tak , jak jest to wyjaśnione na stronie podręcznika errno i w innych odpowiedziach, errno jest lokalną zmienną wątku.
jednak , nie jest głupi szczegół, który mógłby być łatwo zapomnieć. Programy powinny zapisywać i odtwarzać errno w każdym programie obsługi sygnału wykonującym wywołanie systemowe. Dzieje się tak, ponieważ sygnał będzie obsługiwany przez jeden z wątków procesu, który mógłby nadpisać jego wartość.
Dlatego programy obsługi sygnału powinny zapisywać i odtwarzać errno. Coś jak:
źródło
Myślę, że odpowiedź brzmi „to zależy”. Biblioteki środowiska uruchomieniowego C z ochroną wątków zwykle implementują errno jako wywołanie funkcji (makro rozwijające się do funkcji), jeśli tworzysz kod z wątkami z odpowiednimi flagami.
źródło
Możemy to sprawdzić, uruchamiając prosty program na maszynie.
Uruchomienie tego programu i możesz zobaczyć różne adresy dla errno w każdym wątku. Wynik uruchomienia na moim komputerze wyglądał następująco: -
Zauważ, że adres jest inny dla wszystkich wątków.
źródło