GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Ist errno Thread-sicher?

Ja, es ist threadsicher. Unter Linux ist die globale errno-Variable Thread-spezifisch. POSIX erfordert, dass errno threadsicher ist.

Siehe http://www.unix.org/whitepapers/reentrant.html

In POSIX.1 ist errno als externe globale Variable definiert. Aber diese Definition ist in einer Umgebung mit mehreren Threads nicht akzeptabel, da ihre Verwendung zu nicht deterministischen Ergebnissen führen kann. Das Problem besteht darin, dass zwei oder mehr Threads auf Fehler stoßen können, die alle dazu führen, dass dieselbe Fehlernummer gesetzt wird. Unter diesen Umständen kann es vorkommen, dass ein Thread die Fehlernummer überprüft, nachdem er bereits von einem anderen Thread aktualisiert wurde.

Um den daraus resultierenden Nichtdeterminismus zu umgehen, definiert POSIX.1c serrno als Dienst neu, der wie folgt auf die Fehlernummer pro Thread zugreifen kann (ISO/IEC 9945:1-1996, §2.4):

Einige Funktionen können die Fehlernummer in einer Variablen bereitstellen, auf die über das Symbol errno zugegriffen wird. Das Symbol errno wird definiert, indem der Header eingeschlossen wird, wie vom C-Standard spezifiziert ... Für jeden Thread eines Prozesses soll der Wert von errno nicht durch Funktionsaufrufe oder Zuweisungen an errno durch andere Threads beeinflusst werden.

Siehe auch http://linux.die.net/man/3/errno

errno ist Thread-lokal; Wenn Sie es in einem Thread festlegen, wirkt sich dies nicht auf seinen Wert in einem anderen Thread aus.


Ja

Errno ist keine einfache Variable mehr, es ist etwas Komplexes hinter den Kulissen, speziell um Thread-sicher zu sein.

Siehe $ man 3 errno :

ERRNO(3)                   Linux Programmer’s Manual                  ERRNO(3)

NAME
       errno - number of last error

SYNOPSIS
       #include <errno.h>

DESCRIPTION

      ...
       errno is defined by the ISO C standard to be  a  modifiable  lvalue  of
       type  int,  and  must not be explicitly declared; errno may be a macro.
       errno is thread-local; setting it in one thread  does  not  affect  its
       value in any other thread.

Wir können Folgendes überprüfen:

$ cat > test.c
#include <errno.h>
f() { g(errno); }
$ cc -E test.c | grep ^f
f() { g((*__errno_location ())); }
$ 

In errno.h ist diese Variable als extern int errno;

deklariert

Hier ist, was der C-Standard sagt:

Das Makro errno muss nicht der Bezeichner eines Objekts sein. Es kann zu einem änderbaren Lvalue erweitert werden, der sich aus einem Funktionsaufruf ergibt (z. B. *errno() ).

Im Allgemeinen errno ist ein Makro, das eine Funktion aufruft, die die Adresse der Fehlernummer für den aktuellen Thread zurückgibt, und sie dann dereferenziert.

Folgendes habe ich unter Linux in /usr/include/bits/errno.h:

/* Function to get address of global `errno' variable.  */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));

#  if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value.  */
#   define errno (*__errno_location ())
#  endif

Am Ende generiert es diese Art von Code:

> cat essai.c
#include <errno.h>

int
main(void)
{
    errno = 0;

    return 0;
}
> gcc -c -Wall -Wextra -pedantic essai.c
> objdump -d -M intel essai.o

essai.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
   0: 55                    push   ebp
   1: 89 e5                 mov    ebp,esp
   3: 83 e4 f0              and    esp,0xfffffff0
   6: e8 fc ff ff ff        call   7 <main+0x7>  ; get address of errno in EAX
   b: c7 00 00 00 00 00     mov    DWORD PTR [eax],0x0  ; store 0 in errno
  11: b8 00 00 00 00        mov    eax,0x0
  16: 89 ec                 mov    esp,ebp
  18: 5d                    pop    ebp
  19: c3                    ret

Linux
  1. So beenden Sie einen Thread in einem C-Programm (Beispiel pthread_exit)

  2. Wie benenne ich einen Thread in Linux?

  3. WaitForSingleObject und WaitForMultipleObjects äquivalent in Linux?

  4. Detached vs. Joinable POSIX-Threads

  5. strtok-Funktion Thread-Sicherheit

Haben Threads einen bestimmten Haufen?

So drucken Sie pthread_t

Thread-ID vs. Thread-Handle

Ist es sicher, innerhalb eines Threads zu forken?

ID eines Python-Threads, wie von top gemeldet

Verbindung zu MongoDB Fehler Nr. 111 abgelehnt