从上面的映射文件的深蓝色部分中,我们看到,栈的空间总共为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");
}
}