APUE 线程私有数据与errno的实现

线程私有数据

每个线程可以独立地访问数据副本,而不需要担心与其他线程的同步访问问题。

它提供了让基于进程的接口适应多线程环境的机制,一个很明显的实例就是errno。为了让线程也能够使用那些原本基于进程的系统调用和库例程,errno被重新定义为线程私有数据。这样,一个线程设置errno的操作并不会影响进程中其他线程的errno值。

 

#include<pthread.h>

int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *));

“键”可以被进程中的所有线程使用,而每个线程把这个键与不同的线程私有数据地址进行关联,这就是其基本原理。

 

errno的定义

 

在<errno.h>头文件中:

/* Declare the `errno' variable, unless it's defined as a macro by
   bits/errno.h.  This is the case in GNU, where it is a per-thread
   variable.  This redeclaration using the macro still works, but it
   will be a function declaration without a prototype and may trigger
   a -Wstrict-prototypes warning.  */

#ifndef errno
extern int errno;
#endif

在<bits/errno.h>头文件中:

# ifndef __ASSEMBLER__
/* 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
# endif /* !__ASSEMBLER__ */


errno实际上,并不是我们通常认为的是个整型数值,而是通过整型指针来获取值的。这个整型就是线程安全的。

另外,宏之所以这样实现,是因为标准库规定了必须能够通过&errno方式取得保存错误代码的变量的地址,因此__errno_location()函数的返回值是指针,并把宏定义为解引用函数返回的地址*__errno_location()。如果__errno_location直接返回int类型,此时就无法取得保存错误代码的变量的地址。

 

errno的可能实现

 

#include<stdlib.h>
#include<pthread.h>

static pthread_key_t key;
static pthread_once_t init_done = PTHREAD_ONCE_INIT;

static void
thread_init(void)
{
        pthread_key_create(&key, free);
}

int *
__errno_location_simply_fake(void)
{
        int *errp;

        /* 保证多线程环境里 key 只被创建一次 */
        pthread_once(&init_done, thread_init);

        errp = (int *)pthread_getspecific(key);
        if(errp == NULL) {
                errp = malloc(sizeof(int));
                if(errp != NULL)
                        pthread_setspecific(key, errp);
        }

        return errp;
}

 

参考:

1. 《APUE》第12.6节 线程私有数据

2. blog.csdn.net/romandion/archive/2008/01/11/2036975.aspx

3. bbs.chinaunix.net/viewthread.php

 

linux errno code

 

来源: blog.csdn.net/wei801004/archive/2007/03/05/1521100.aspx

   124 EMEDIUMTYPE   Wrong medium type
   123 ENOMEDIUM     No medium found
   122 EDQUOT        Disk quota exceeded
   121 EREMOTEIO     Remote I/O error
   120 EISNAM        Is a named type file
   119 ENAVAIL       No XENIX semaphores available
   118 ENOTNAM       Not a XENIX named type file
   117 EUCLEAN       Structure needs cleaning
   116 ESTALE        Stale NFS file handle
   115 EINPROGRESS  +Operation now in progress
   114 EALREADY      Operation already in progress
   113 EHOSTUNREACH  No route to host
   112 EHOSTDOWN     Host is down
   111 ECONNREFUSED  Connection refused
   110 ETIMEDOUT    +Connection timed out
   109 ETOOMANYREFS  Too many references: cannot splice
   108 ESHUTDOWN     Cannot send after transport endpoint shutdown
   107 ENOTCONN      Transport endpoint is not connected
   106 EISCONN       Transport endpoint is already connected
   105 ENOBUFS       No buffer space available
   104 ECONNRESET    Connection reset by peer
   103 ECONNABORTED  Software caused connection abort
   102 ENETRESET     Network dropped connection on reset
   101 ENETUNREACH   Network is unreachable
   100 ENETDOWN      Network is down
    99 EADDRNOTAVAIL Cannot assign requested address
    98 EADDRINUSE    Address already in use
    97 EAFNOSUPPORT  Address family not supported by protocol
    96 EPFNOSUPPORT  Protocol family not supported
    95 EOPNOTSUPP    Operation not supported
    94 ESOCKTNOSUPPORT Socket type not supported
    93 EPROTONOSUPPORT Protocol not supported
    92 ENOPROTOOPT   Protocol not available
    91 EPROTOTYPE    Protocol wrong type for socket
    90 EMSGSIZE     +Message too long
    89 EDESTADDRREQ  Destination address required
    88 ENOTSOCK      Socket operation on non-socket
    87 EUSERS        Too many users
    86 ESTRPIPE      Streams pipe error
    85 ERESTART      Interrupted system call should be restarted
    84 EILSEQ        Invalid or incomplete multibyte or wide character
    83 ELIBEXEC      Cannot exec a shared library directly
    82 ELIBMAX       Attempting to link in too many shared libraries
    81 ELIBSCN       .lib section in a.out corrupted
    80 ELIBBAD       Accessing a corrupted shared library
    79 ELIBACC       Can not access a needed shared library
    78 EREMCHG       Remote address changed
    77 EBADFD        File descriptor in bad state
    76 ENOTUNIQ      Name not unique on network
    75 EOVERFLOW     Value too large for defined data type
    74 EBADMSG      +Bad message
    73 EDOTDOT       RFS specific error
    72 EMULTIHOP     Multihop attempted
    71 EPROTO        Protocol error
    70 ECOMM         Communication error on send
    69 ESRMNT        Srmount error
    68 EADV          Advertise error
    67 ENOLINK       Link has been severed
    66 EREMOTE       Object is remote
    65 ENOPKG        Package not installed
    64 ENONET        Machine is not on the network
    63 ENOSR         Out of streams resources
    62 ETIME         Timer expired
    61 ENODATA       No data available
    60 ENOSTR        Device not a stream
    59 EBFONT        Bad font file format
    57 EBADSLT       Invalid slot
    56 EBADRQC       Invalid request code
    55 ENOANO        No anode
    54 EXFULL        Exchange full
    53 EBADR         Invalid request descriptor
    52 EBADE         Invalid exchange
    51 EL2HLT        Level 2 halted
    50 ENOCSI        No CSI structure available
    49 EUNATCH       Protocol driver not attached
    48 ELNRNG        Link number out of range
    47 EL3RST        Level 3 reset
    46 EL3HLT        Level 3 halted
    45 EL2NSYNC      Level 2 not synchronized
    44 ECHRNG        Channel number out of range
    43 EIDRM         Identifier removed
    42 ENOMSG        No message of desired type
    40 ELOOP         Too many levels of symbolic links
    39 ENOTEMPTY    +Directory not empty
    38 ENOSYS       +Function not implemented
    37 ENOLCK       +No locks available
    36 ENAMETOOLONG +File name too long
    35 EDEADLK      +Resource deadlock avoided
    34 ERANGE       +Numerical result out of range
    33 EDOM         +Numerical argument out of domain
    32 EPIPE        +Broken pipe
    31 EMLINK       +Too many links
    30 EROFS        +Read-only file system
    29 ESPIPE       +Illegal seek
    28 ENOSPC       +No space left on device
    27 EFBIG        +File too large
    26 ETXTBSY       Text file busy
    25 ENOTTY       +Inappropriate ioctl for device
    24 EMFILE       +Too many open files
    23 ENFILE       +Too many open files in system
    22 EINVAL       +Invalid argument
    21 EISDIR       +Is a directory
    20 ENOTDIR      +Not a directory
    19 ENODEV       +No such device
    18 EXDEV        +Invalid cross-device link
    17 EEXIST       +File exists
    16 EBUSY        +Device or resource busy
    15 ENOTBLK       Block device required
    14 EFAULT       +Bad address
    13 EACCES       +Permission denied
    12 ENOMEM       +Cannot allocate memory
    11 EAGAIN       +Resource temporarily unavailable
    10 ECHILD       +No child processes
     9 EBADF        +Bad file descriptor
     8 ENOEXEC      +Exec format error
     7 E2BIG        +Argument list too long
     6 ENXIO        +No such device or address
     5 EIO          +Input/output error
     4 EINTR        +Interrupted system call
     3 ESRCH        +No such process
     2 ENOENT       +No such file or directory
     1 EPERM        +Operation not permitted
#    0 --            Success