从上面的映射文件的深蓝色部分中,我们看到,栈的空间总共为10244Kb,内存段是从b6d1d000到b771e000。从strace的输出中,我们看到栈底的地址为0xb771c494,那么,从0xb771c494到b771e000这段内存是做什么用的呢?它就是线程的TCB(thread's control block)和TLS区域(thread's local storage)。具体的线程内存空间布局如下:
[root@yjye .libs]# nm libapr-1.a | grep pthread U pthread_rwlock_destroy U pthread_rwlock_init U pthread_rwlock_rdlock U pthread_rwlock_tryrdlock U pthread_rwlock_trywrlock U pthread_rwlock_unlock U pthread_rwlock_wrlock U pthread_mutex_destroy U pthread_mutex_init U pthread_mutex_lock U pthread_mutex_trylock U pthread_mutex_unlock U pthread_mutexattr_destroy U pthread_mutexattr_init U pthread_mutexattr_settype U pthread_cond_broadcast U pthread_cond_destroy U pthread_cond_init U pthread_cond_signal U pthread_cond_timedwait U pthread_cond_wait 00000080 d mutex_proc_pthread_methods 00000a10 t proc_mutex_proc_pthread_acquire 00000990 t proc_mutex_proc_pthread_cleanup 00000a50 t proc_mutex_proc_pthread_create 00000960 t proc_mutex_proc_pthread_release U pthread_mutex_destroy U pthread_mutex_init U pthread_mutex_lock U pthread_mutex_unlock U pthread_mutexattr_destroy U pthread_mutexattr_init U pthread_mutexattr_setprotocol U pthread_mutexattr_setpshared U pthread_mutexattr_setrobust_np U pthread_attr_destroy U pthread_attr_getdetachstate U pthread_attr_init U pthread_attr_setdetachstate U pthread_attr_setguardsize U pthread_attr_setstacksize U pthread_create U pthread_detach U pthread_exit U pthread_join U pthread_once U pthread_self U pthread_sigmask U pthread_getspecific U pthread_key_create U pthread_key_delete U pthread_setspecific
int __pthread_create_2_0 (newthread, attr, start_routine, arg) pthread_t *newthread; const pthread_attr_t *attr; void *(*start_routine) (void *); void *arg; { /* The ATTR attribute is not really of type `pthread_attr_t *'. It has the old size and access to the new members might crash the program. We convert the struct now. */ struct pthread_attr new_attr;
/* Copy values from the user-provided attributes. */ new_attr.schedparam = iattr->schedparam; new_attr.schedpolicy = iattr->schedpolicy; new_attr.flags = iattr->flags;
/* Fill in default values for the fields not present in the old implementation. */ new_attr.guardsize = ps; new_attr.stackaddr = NULL; new_attr.stacksize = 0; new_attr.cpuset = NULL;
/* We will pass this value on to the real implementation. */ attr = (pthread_attr_t *) &new_attr; }
// Get the version GLIBC_2.1 of pthread_create() symbol pSym = dlvsym(RTLD_DEFAULT, "pthread_create", "GLIBC_2.1"); if (NULL == pSym) { lxb_pthread_create = pthread_create; } else { lxb_pthread_create = (lxb_pcreate_t)pSym; if (pSym != (void *)pthread_create) { LXB_PRINTF("Unexpected version of pthread_create() symbol ==> Forced to GLIBC_2.1\n"); } }