如何实现在linux中 pthread

博客访问: 70904
博文数量: 21
博客积分: 508
博客等级: 下士
技术积分: 306
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: LINUX
Outline& - 1.线程特点 - 2.pthread创建 - 3.pthread终止& & & & - 4.mutex互斥量使用框架& & & & - 5.cond条件变量& & & & - 6.综合实例================================================================================================1. 线程特点线程拥有自己独立的栈、调度优先级和策略、信号屏蔽字(创建时继承)、errno变量以及线程私有数据。进程的其他地址空间均被所有线程所共享,因此线程可以访问程序的全局变量和堆中分配的数据,并通过同步机制保证对数据访问的一致性。2. pthread创建pthread有一个线程ID,类型为pthread_t,在使用printf打印时,应转换为u类型。pthread_equal可用于比较两个id是否相等;pthread_self用于获取当前线程的ID。pthread_create用于创建新的线程,可以给线程传入一个void *类型的参数,例如一个结构体指针或者一个数值。系统并不能保证哪个线程会现运行:新创建的线程还是调用线程。3. pthread终止a) 从线程函数中返回b) 被同一进程中的其他线程取消c) 线程调用pthread_exit注意,线程的返回值需要转换为void *类型。pthread_exit(void *ret)pthread_join(pthread_t id, void **ret)ret均可设置为NULL4. &mutex 互斥量使用框架pthread_mutex_pthread_mutex_init 或者 PTHREAD_MUTEX_INITIALIZER(仅可用在静态变量)pthread_mutex_lock / pthread_mutex_unlock / pthread_mutex_trylockpthread_mutex_destroy<font class="Apple-style-span" color="#. cond 条件变量pthread_cond_pthread_mutex_pthread_mutex_init 或者 PTHREAD_MUTEX_INITIALIZERpthread_cond_init 或者 PTHREAD_COND_INITIALIZERpthread_mutex_lock(&qlock...)pthread_cond_wait(&qready, &qlock...) / pthread_cond_timewaitpthread_mutex_unlock(&qlock)pthread_cond_destroy//唤醒条件变量pthread_cond_signalpthread_cond_broadcast条件变量是pthread中比较难以理解的一点,主要会产生以下疑惑:Q1. 假如在调用pthread_{cond_wait | cond_timedwait}之前就调用pthread_cond_{signal | broadcast}会发生什么?Q2. pthread_cond_{cond_wait | cond_timewait}为什么需要一个已经锁住的mutex作为变量?Q3. pthread_cond_{signal | broadcast}使用之前必须获取wait中对应的mutex吗?Q4. 假如pthread_cond_{signal | broadcast}必须获取mutex,那么下列两种形式,哪种正确?为什么?&1)&lock(lock_for_X);&change(X);&unlock(lock_for_X);&pthread_cond_{signal | broadcast};&2)&lock(lock_for_X);&change(X);&pthread_cond_{signal | broadcast};&unlock(lock_for_X);----思考-------思考-------思考-------思考------思考-------思考------思考------思考-------思考-------A1: 什么都不会发生,也不会出错,仅仅造成这次发送的signal丢失。A2: 一般场景如下,我们需要检查某个条件是否满足(如队列X是否为空、布尔Y是否为真),假如没有条件变量,我们唯一的选择是while (1) {
&&lock(lock_for_X);
&&if (X is not empty) {
&&&&unlock(lock_for_X);
&&&&break;
&&} else {
//X is empty, loop continues
&&&&unlock(lock_for_X);
&&&&sleep(10);
//X is not empty, loop ends
process(X);明显这种轮询的方式非常耗费CPU时间,这时候我们很容易的想到,如果有一种机制,可以异步通知我们队列的状态发生了变化,那么我们便无须再轮询,只要等到通知到来时再检查条件是否满足即可,其他时间则将程序休眠,因此现在代码变成这样:while (1) {
&&lock(lock_for_X);
&&if (X is not empty) {
&&&&unlock(lock_for_X);
&&&&break;
&&} else {
&&&&unlock(lock_for_X); //must called before my_wait(), otherwise
no one can acquire the lock and make change to X
&&&&--------------------------------------&窗口,由于已经解锁,其他程序可能改变X,并且试图唤醒mywait,但在一个繁忙的系统中,可能此时my_还没被调用!
&&&&my_wait(); //go to sleep and wait for the notification
}my_wait是一个假想的函数,作用如注释所示。不难发现,这样做以后,我们无须再轮询了,只需要等待my_wait()被唤醒以后检查条件是否满足。但是请注意,正如图中所示,存在1个时间窗口。若其他程序在这个窗口中试图唤醒my_wait,由于此时my_wait还没有被调用,那么这个信号将丢失,造成my_wait一直阻塞。解决的办法就是,要将unlock和my_wait合并成一个原子操作,这样就不会被其他程序插入执行。我想到这里,你应该已经明白了,这个原子操作的函数就是pthread_cond_{signal | broadcast}.A3: 是的。详见:A4: 对于1),在不同的操作系统中,可能会造成不确定的调度结果(可能会造成调度优先级反转);对于2)可以保证无论在何种操作系统中都将获得预期的调度顺序。设想一个场景:有两个消费者线程A和B,我们设定A的优先级比B高,A正在等待条件变量被出发,即已经调用了pthread_wait,并且处于阻塞状态:lock(lock_for_X);
while (X is empty) {
&&pthread_cond_wait(&qready, &lock_for_X);
unlock(lock_for_X);B中没有调用pthread_wait,而是做类似如下的处理:while(1) {
&&lock(lock_for_X);
&&dequeue(X);
&&unlock(lock_for_X);
}另一个线程C,为生产者,采用1)方案,则代码如下,先unlock,再发出signal:&lock(lock_for_X);&change(X);&unlock(lock_for_X);&pthread_cond_{signal | broadcast};当发出unlock以后,发送signal之前,此时消费者B已经满足了运行条件,而消费者A虽然优先级比B高,但是由于其运行条件还需要signal,所以不具备立刻运行的条件,此时就看操作系统如何实现调度算法了。有些操作系统,可能会因为A不具备立刻运行条件,即使它的优先级比B高,此时还是让B线程先运行,那么,后续将分成两种情况:(a) B获得了lock,但是还没有将X队列中的刚刚加入的条目移除,此时C调用了signal,A接收到了signal,由于A的优先级高,那么A抢占B,A从函数pthread_cond_wait返回之前需要再次将lock上锁,但是A抢占后发现,lock被人锁住了(还没有被B释放),只好再次休眠,等待锁被释放,结果B又被唤醒,也可能因此造成A和B的死锁,这个具体要看操作系统的调度算法。(b) B获得了lock,并且执行了dequeue,然后释放了锁。此时C调用了signal,A接收到了signal,由于A的优先级高,那么A抢占B,A这次顺利的获取了锁得以从pthread_cond_wait中返回,但是在检查条件时,却发现队列是空的,于是乎再次进入pthread_cond_wait休眠。结果A又无法被执行,A可能由此进入饥饿状态。但是如果C采用2)方案:&lock(lock_for_X);&change(X);&pthread_cond_{signal | broadcast};&unlock(lock_for_X);在unlock以后,A、B都具备了立即运行的条件,由于A比B的优先级高,因此操作系统必定会先调度A执行,就避免了前面一种不确定的调度结果。主要参考:<font class="Apple-style-span" color="#. 综合实例/*
&* =====================================================================================
Description:
08/17/11 11:06:35
YOUR NAME (),
&* =====================================================================================
#include &stdio.h&
#include &pthread.h&
#include &error.h&
#include &stdlib.h&
#include &unistd.h&
#include &string.h&
pthread_cond_t qready;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
struct foo {
&&&&int cnt;
&&&&pthread_mutex_t f_lock;
void cleanup(void *arg)
&&&&printf("clean up: %s\n", (char *)arg);
void printids(char *str)
&&&&printf("%s pid = %u tid = %u / 0x%x\n",
&&&&&&&&&&&&str, (unsigned int)getpid(), (unsigned int)pthread_self(), (unsigned int)pthread_self());
void *thread1(void *arg)
&&&&pthread_mutex_lock(&qlock);
&&&&pthread_cond_wait(&qready, &qlock);
&&&&pthread_mutex_unlock(&qlock);
&&&&printids("thread1:");
&&&&pthread_cleanup_push(cleanup, "thread 1 first cleanup handler");
&&&&pthread_cleanup_push(cleanup, "thread 1 second cleanup handler");
&&&&printf("thread 1 push complete!\n");
&&&&pthread_mutex_lock(&((struct foo *)arg)-&f_lock);
&&&&((struct foo *)arg)-&cnt
&&&&printf("thread1: cnt = %d\n", ((struct foo *)arg)-&cnt);
&&&&pthread_mutex_unlock(&((struct foo *)arg)-&f_lock);
&&&&if (arg)
&&&&&&&&return ((void *)0);
&&&&pthread_cleanup_pop(0);
&&&&pthread_cleanup_pop(0);
&&&&pthread_exit((void *)1);
void *thread2(void *arg)
&&&&int exit_code = -1;
&&&&printids("thread2:");
&&&&printf("Now unlock thread1\n");
&&&&pthread_mutex_lock(&qlock);
&&&&pthread_mutex_unlock(&qlock);
&&&&pthread_cond_signal(&qready);
&&&&printf("Thread1 unlocked\n");
&&&&pthread_cleanup_push(cleanup, "thread 2 first cleanup handler");
&&&&pthread_cleanup_push(cleanup, "thread 2 second cleanup handler");
&&&&printf("thread 2 push complete!\n");
&&&&if (arg)
&&&&&&&&pthread_exit((void *)exit_code);
&&&&pthread_cleanup_pop(0);
&&&&pthread_cleanup_pop(0);
&&&&pthread_exit((void *)exit_code);
int main(int argc, char *argv[])
&&&&int ret;
&&&&pthread_t tid1, tid2;
&&&&void *retval;
&&&&struct foo *fp;
&&&&ret = pthread_cond_init(&qready, NULL);
&&&&if (ret != 0) {
&&&&&&&&printf("pthread_cond_init error: %s\n", strerror(ret));
&&&&&&&&return -1;
&&&&if ((fp = malloc(sizeof(struct foo))) == NULL) {
&&&&&&&&printf("malloc failed!\n");
&&&&&&&&return -1;
&&&&if (pthread_mutex_init(&fp-&f_lock, NULL) != 0) {
&&&&&&&&free(fp);
&&&&&&&&printf("init mutex failed!\n");
&&&&pthread_mutex_lock(&fp-&f_lock);
&&&&ret = pthread_create(&tid1, NULL, thread1, (void *)fp);
&&&&if (ret != 0) {
&&&&&&&&printf("main thread error: %s\n", strerror(ret));
&&&&&&&&return -1;
&&&&ret = pthread_create(&tid2, NULL, thread2, (void *)1);
&&&&if (ret != 0) {
&&&&&&&&printf("main thread error: %s\n", strerror(ret));
&&&&&&&&return -1;
&&&&ret = pthread_join(tid2, &retval);
&&&&if (ret != 0) {
&&&&&&&&printf("pthread join falied!\n");
&&&&&&&&return -1;
&&&&&&&&printf("thread2 exit code %d\n", (int)retval);
&&&&fp-&cnt = 1;
&&&&printf("main thread: cnt = %d\n",fp-&cnt);
&&&&pthread_mutex_unlock(&fp-&f_lock);
&&&&sleep(1);&&&&//there is no guarantee the main thread will run before the newly created thread, so we wait for a while
&&&&printids("main thread:");
&&&&printf("Press &RETURN& to exit\n");
&&&&ret = pthread_cond_destroy(&qready);
&&&&if (ret != 0) {
&&&&&&&&printf("pthread_cond_destroy error: %s\n", strerror(ret));
&&&&&&&&return -1;
&&&&getchar();
&&&&return 0;
阅读(24580) | 评论(0) | 转发(9) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。linux线程pthread_create的源码分析 - Linux系统 - 编程入门网
linux线程pthread_create的源码分析
int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,
void * (*start_routine)(void *), void *arg)
// thread 为pthread_t,实则是pthread指针。
// typedef struct pthread *pthread_t; ->unsigned long int
// attr 创建线程时的附加属性
// start_routine 执行的线程函数
// arg参数首地址指针
pthread_descr self = thread_self();
// 向管理线程的请求
struct pthread_
// 在初始化时 全局 int __pthread_manager_request = -1;
if (__pthread_manager_request & 0) {
// 首先Linuxthreads需要有__pthread_manager_thread,这个线程是个很特殊的线程
// 初始化Linuxthreads系统线程
if (__pthread_initialize_manager() & 0) return EAGAIN;
request.req_thread =
// 请求类型 CREATE ,并将新线程(轻量进程)的参数都打包到request结构中。
request.req_kind = REQ_CREATE;
request.req_args.create.attr =
request.req_args.create.fn = start_
request.req_args.create.arg =
//sigprocmask用于改变进程的当前阻塞信号集
sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
&request.req_args.create.mask);
// 向__pthread_manager_request写入request请求。 request请求将被_pthread_manager_thread读取并处理。
__libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
// 挂起一下
suspend(self);
if (THREAD_GETMEM(self, p_retcode) == 0)
*thread = (pthread_t) THREAD_GETMEM(self, p_retval);
return THREAD_GETMEM(self, p_retcode);
#if defined HAVE_ELF && defined PIC && defined DO_VERSIONING
default_symbol_version (__pthread_create_2_1, pthread_create, GLIBC_2.1);
int __pthread_create_2_0(pthread_t *thread, 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. */
pthread_attr_t new_
if (attr != NULL)
size_t ps = __getpagesize ();
memcpy (&new_attr, attr,
(size_t) &(((pthread_attr_t*)NULL)->__guardsize));
new_attr.__guardsize =
new_attr.__stackaddr_set = 0;
new_attr.__stackaddr = NULL;
new_attr.__stacksize = STACK_SIZE -
attr = &new_
return __pthread_create_2_1 (thread, attr, start_routine, arg);
symbol_version (__pthread_create_2_0, pthread_create, GLIBC_2.0); // 由此可知pthread_create入口函数为__pthread_create_2_1
strong_alias (__pthread_create_2_1, pthread_create)
由上面的函数可知,pthread_create对线程的创建实际上是向pthread_manager_thread发送个request请求。
下面我们就看pthread_manager_thread是怎样初始化的:
首先要进行基本系统的初始化工作:
即填充__pthread_initial_thread(算是模板吧?)其他属性:
/* Descriptor of the initial thread */
struct _pthread_descr_struct __pthread_initial_thread = {
&__pthread_initial_thread, /* pthread_descr p_nextlive */ // 将进程中所有用户线程串在了一起
&__pthread_initial_thread, /* pthread_descr p_prevlive */
NULL, /* pthread_descr p_nextwaiting */
NULL, /* pthread_descr p_nextlock */
PTHREAD_THREADS_MAX, /* pthread_t p_tid */
0, /* int p_pid */
0, /* int p_priority */
&__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */
0, /* int p_signal */
NULL, /* sigjmp_buf * p_signal_buf */
NULL, /* sigjmp_buf * p_cancel_buf */
0, /* char p_terminated */
0, /* char p_detached */
0, /* char p_exited */
NULL, /* void * p_retval */
0, /* int p_retval */
NULL, /* pthread_descr p_joining */
NULL, /* struct _pthread_cleanup_buffer * p_cleanup */
0, /* char p_cancelstate */
0, /* char p_canceltype */
0, /* char p_canceled */
NULL, /* int *p_errnop */
0, /* int p_errno */
NULL, /* int *p_h_errnop */
0, /* int p_h_errno */
NULL, /* char * p_in_sighandler */
0, /* char p_sigwaiting */
PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
{NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
{NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
0, /* int p_userstack */
NULL, /* void * p_guardaddr */
0, /* size_t p_guardsize */
&__pthread_initial_thread, /* pthread_descr p_self */
0, /* Always index 0 */
0, /* int p_report_events */
{{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */
ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */
0, /* char p_woken_by_cancel */
NULL /* struct pthread_extricate_if *p_extricate */
static void pthread_initialize(void)
//__pthread_initial_thread_bos: Limit between the stack of the initial thread (above) and the
//stacks of other threads (below). Aligned on a STACK_SIZE boundary.
/* 如果初始化工作已完成,则退出 */
if (__pthread_initial_thread_bos != NULL)
#ifdef TEST_FOR_COMPARE_AND_SWAP
/* Test if compare-and-swap is available */
__pthread_has_cas = compare_and_swap_is_available();
/* For the initial stack, reserve at least STACK_SIZE bytes of stack
below the current stack address, and align that on a
STACK_SIZE boundary. */
__pthread_initial_thread_bos =
(char *)(((long)CURRENT_STACK_FRAME. - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
/* 对initial_thread.pid赋值:主进程pid */
__pthread_initial_thread.p_pid = __getpid();
/* If we have special thread_self processing, initialize that for the
main thread now. */
#ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(&__pthread_initial_thread, 0);
/* 共享主进程errno/h_errno.*/
__pthread_initial_thread.p_errnop = &_
__pthread_initial_thread.p_h_errnop = &_h_
/* Play with the stack size limit to make sure that no stack ever grows
beyond STACK_SIZE minus two pages (one page for the thread descriptor
immediately beyond, and one page to act as a guard page). */
getrlimit(RLIMIT_STACK, &limit); // 获取STACK limit
max_stack = STACK_SIZE - 2 * __getpagesize();
if (limit.rlim_cur > max_stack) {
limit.rlim_cur = max_
setrlimit(RLIMIT_STACK, &limit);
#ifdef __SIGRTMIN
/* Initialize real-time signals. */
init_rtsigs ();
/* Setup signal handlers for the initial thread.
Since signal handlers are shared between threads, these settings
will be inherited by all other threads. */
// 设置initial thread信号处理函数 其他线程都将继承
#ifndef __i386__
sa.sa_handler = pthread_handle_
sa.sa_handler = (__sighandler_t) pthread_handle_
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
__sigaction(__pthread_sig_restart, &sa, NULL);
#ifndef __i386__
sa.sa_handler = pthread_handle_
sa.sa_handler = (__sighandler_t) pthread_handle_
sa.sa_flags = 0;
__sigaction(__pthread_sig_cancel, &sa, NULL);
if (__pthread_sig_debug > 0) {
sa.sa_handler = pthread_handle_
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
__sigaction(__pthread_sig_debug, &sa, NULL);
/* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
sigemptyset(&mask);
sigaddset(&mask, __pthread_sig_restart);
sigprocmask(SIG_BLOCK, &mask, NULL);
/* Register an exit function to kill all other threads. */
/* Do it early so that user-registered atexit functions are called
before pthread_exit_process. */
__on_exit(pthread_exit_process, NULL);
// 下面是__pthread_manager_thread 的初始化
/* Descriptor o none of this is used but the error
variables, the p_pid and p_priority fields,
and the address for identification. */
struct _pthread_descr_struct __pthread_manager_thread = {
NULL, /* pthread_descr p_nextlive */ // 这两个值为空!
NULL, /* pthread_descr p_prevlive */
NULL, /* pthread_descr p_nextwaiting */
NULL, /* pthread_descr p_nextlock */
0, /* int p_tid */
0, /* int p_pid */
0, /* int p_priority */
&__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */
0, /* int p_signal */
NULL, /* sigjmp_buf * p_signal_buf */
NULL, /* sigjmp_buf * p_cancel_buf */
0, /* char p_terminated */
0, /* char p_detached */
0, /* char p_exited */
NULL, /* void * p_retval */
0, /* int p_retval */
NULL, /* pthread_descr p_joining */
NULL, /* struct _pthread_cleanup_buffer * p_cleanup */
0, /* char p_cancelstate */
0, /* char p_canceltype */
0, /* char p_canceled */
&__pthread_manager_thread.p_errno, /* int *p_errnop */
0, /* int p_errno */
NULL, /* int *p_h_errnop */
0, /* int p_h_errno */
NULL, /* char * p_in_sighandler */
0, /* char p_sigwaiting */
PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
{NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
{NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
0, /* int p_userstack */
NULL, /* void * p_guardaddr */
0, /* size_t p_guardsize */
&__pthread_manager_thread, /* pthread_descr p_self */
1, /* Always index 1 */
0, /* int p_report_events */
{{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */
ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */
0, /* char p_woken_by_cancel */
NULL /* struct pthread_extricate_if *p_extricate */
int __pthread_initialize_manager(void)
// 管理线程与其他线程之间的通信是通过管道完成的。
/*在一个进程空间内,管理线程与其他线程之间通过一对&管理管道(manager_pipe[2])&来通讯,
该管道在创建管理线程之前创建,在成功启动了管理线程之后,管理管道的读端和写端分别赋给两个全局变量
__pthread_manager_reader和__pthread_manager_request,之后,每个用户线程都通过
__pthread_manager_request向管理线程发请求,但管理线程本身并没有直接使用__pthread_manager_reader,
管道的读端(manager_pipe[0])是作为__clone()的参数之一传给管理线程的,
管理线程的工作主要就是监听管道读端,并对从中取出的请求作出反应。*/
int manager_pipe[2];
struct pthread_
/* 如果基本的初始化未进行,那么进行初始化*/
if (__pthread_initial_thread_bos == NULL) pthread_initialize();
/* 设置stack */
__pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
if (__pthread_manager_thread_bos == NULL) return -1;
__pthread_manager_thread_tos =
__pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
/* 设置通信管道 */
if (pipe(manager_pipe) == -1) {
free(__pthread_manager_thread_bos);
return -1;
/* 在创建线程时 pid一定不会为0 */
if (__pthread_initial_thread.p_report_events)
/* It's a bit more complicated. We have to report the creation of
the manager thread. */
int idx = __td_eventword (TD_CREATE);
uint32_t mask = __td_eventmask (TD_CREATE);
if ((mask & (__pthread_threads_events.event_bits[idx]
| __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
// sys_fork:创建 pthread_manager线程 :共享VM FS FILES等
pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]); // 读管道
if (pid != -1)
/* Now fill in the information about the new thread in
the newly created thread's data structure. We cannot let
the new thread do this since we don't know whether it was
already scheduled when we send the event. */
// 对新线程添加属性
__pthread_manager_thread.p_eventbuf.eventdata =
&__pthread_manager_
__pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
__pthread_last_event = &__pthread_manager_
// _pthread_manager_thread的是2*PTHREAD_THREADS_MAX+1
__pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_thread.p_pid = // clone进程pid
/* Now call the function which signals the event. */
__linuxthreads_create_event ();
/* Now restart the thread. */
__pthread_unlock(__pthread_manager_thread.p_lock);
// 如果__pthread_initial_thread.p_report_events标记了,自然不再创建新线程了
if (pid == 0)
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
if (pid == -1) {
free(__pthread_manager_thread_bos);
__libc_close(manager_pipe[0]);
__libc_close(manager_pipe[1]);
return -1;
// __pthread_manager_request fd = manager_pipe[1]; 交给其他线程写请求
__pthread_manager_request = manager_pipe[1]; /* 全局变量writing end */
__pthread_manager_reader = manager_pipe[0]; /* 全局变量reading end */
__pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
__pthread_manager_thread.p_pid =
/* Make gdb aware of new thread manager */
if (__pthread_threads_debug && __pthread_sig_debug > 0)
raise(__pthread_sig_debug);
/* We suspend ourself and gdb will wake us up when it is
ready to handle us. */
__pthread_wait_for_restart_signal(thread_self());
/* Synchronize debugging of the thread manager */
request.req_kind = REQ_DEBUG;
__libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
至此,__pthread_manager_thread创建成功。
下面看看它是怎样管理的:__pthread_manager函数
/* The server thread managing requests for thread creation and termination */
int __pthread_manager(void *arg)
int reqfd = (int) (long int) // 管道的读口fd
struct pthread_
/* If we have special thread_self processing, initialize it. */
#ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(&__pthread_manager_thread, 1);
/* Set the error variable. */
__pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_
__pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_
/* Block all signals except __pthread_sig_cancel and SIGTRAP */
sigfillset(&mask);
sigdelset(&mask, __pthread_sig_cancel); /* for thread termination */
sigdelset(&mask, SIGTRAP); /* for debugging purposes */
sigprocmask(SIG_SETMASK, &mask, NULL);
/* 提高优先级 等于主线程的优先级 */
__pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
/* Synchronize debugging of the thread manager */
// 从管道中读取请求
n = __libc_read(reqfd, (char *)&request, sizeof(request));
ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
ufd.events = POLLIN;
/* Enter server loop */
while(1) {
n = __poll(&ufd, 1, 2000); // 2秒超时
/* main thread的终止 将导致所有thread终止 */
if (getppid() == 1) {
pthread_kill_all_threads(SIGKILL, 0);
/* Check for dead children */
if (terminated_children) {
terminated_children = 0;
pthread_reap_children();
/* 读取请求 */
if (n == 1 && (ufd.revents & POLLIN)) {
n = __libc_read(reqfd, (char *)&request, sizeof(request));
ASSERT(n == sizeof(request));
switch(request.req_kind) {
case REQ_CREATE: //创建
request.req_thread->p_retcode =
pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
request.req_args.create.attr,
request.req_args.create.fn,
request.req_args.create.arg,
&request.req_args.create.mask,
request.req_thread->p_pid,
request.req_thread->p_report_events,
&request.req_thread->p_eventbuf.eventmask);
restart(request.req_thread);
case REQ_FREE:
pthread_handle_free(request.req_args.free.thread_id);
case REQ_PROCESS_EXIT:
pthread_handle_exit(request.req_thread,
request.req_args.exit.code);
case REQ_MAIN_THREAD_EXIT:
main_thread_exiting = 1;
if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
restart(__pthread_main_thread);
case REQ_POST:
__new_sem_post(request.req_args.post);
case REQ_DEBUG:
/* Make gdb aware of new thread and gdb will restart the
new thread when it is ready to handle the new thread. */
if (__pthread_threads_debug && __pthread_sig_debug > 0)
raise(__pthread_sig_debug);
下面我们看看新的线程是怎样创建的:
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
void * (*start_routine)(void *), void *arg,
sigset_t * mask, int father_pid,
int report_events,
td_thr_events_t *event_maskp)
pthread_descr new_
char * new_thread_
pthread_t new_thread_
char *guardaddr = NULL;
size_t guardsize = 0;
int pagesize = __getpagesize();
/* First check whether we have to change the policy and if yes, whether
we can do this. Normally this should be done by examining the
return value of the __sched_setscheduler call in pthread_start_thread
but this is hard to implement. FIXME */
if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
return EPERM;
/* Find a free segment for the thread, and allocate a stack if needed */
for (sseg = 2; ; sseg++)
if (sseg >= PTHREAD_THREADS_MAX)
return EAGAIN;
if (__pthread_handles[sseg].h_descr != NULL)
if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize,
&new_thread, &new_thread_bottom,
&guardaddr, &guardsize) == 0)
__pthread_handles_num++;
/* Allocate new thread identifier */
pthread_threads_counter += PTHREAD_THREADS_MAX;
new_thread_id = sseg + pthread_threads_
/* Initialize the thread descriptor. Elements which have to be
initialized to zero already have this value. */
// 对新的线程进行属性赋值
new_thread->p_tid = new_thread_ //tid=n*PTHREAD_THREADS_MAX+n+1
new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
new_thread->p_errnop = &new_thread->p_
new_thread->p_h_errnop = &new_thread->p_h_
new_thread->p_guardaddr =
new_thread->p_guardsize =
new_thread->p_self = new_
new_thread->p_nr =
/* Initialize the thread handle */
__pthread_init_lock(&__pthread_handles[sseg].h_lock);
__pthread_handles[sseg].h_descr = new_
__pthread_handles[sseg].h_bottom = new_thread_
/* Determine scheduling parameters for the thread */
new_thread->p_start_args.schedpolicy = -1;
if (attr != NULL) {
new_thread->p_detached = attr->__
new_thread->p_userstack = attr->__stackaddr_
switch(attr->__inheritsched) {
case PTHREAD_EXPLICIT_SCHED:
new_thread->p_start_args.schedpolicy = attr->__
memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
sizeof (struct sched_param));
case PTHREAD_INHERIT_SCHED:
new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid);
__sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
new_thread->p_priority =
new_thread->p_start_args.schedparam.sched_
/* Finish setting up arguments to pthread_start_thread */
// 新线程 函数 参数赋值
new_thread->p_start_args.start_routine = start_
new_thread->p_start_args.arg =
new_thread->p_start_args.mask = *
/* Raise priority of thread manager if needed */
__pthread_manager_adjust_prio(new_thread->p_priority);
/* Do the cloning. We have to use two different functions depending
on whether we are debugging or not. */
pid = 0; /* Note that the thread never can have PID zero. */
if (report_events)
/* See whether the TD_CREATE event bit is set in any of the
int idx = __td_eventword (TD_CREATE);
uint32_t mask = __td_eventmask (TD_CREATE);
if ((mask & (__pthread_threads_events.event_bits[idx]
| event_maskp->event_bits[idx])) != 0)
/* Lock the mutex the child will use now so that it will stop. */
__pthread_lock(new_thread->p_lock, NULL);
/* We have to report this event. */
pid = __clone(pthread_start_thread_event, (void **) new_thread,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
__pthread_sig_cancel, new_thread);
if (pid != -1)
/* Now fill in the information about the new thread in
the newly created thread's data structure. We cannot let
the new thread do this since we don't know whether it was
already scheduled when we send the event. */
new_thread->p_eventbuf.eventdata = new_
new_thread->p_eventbuf.eventnum = TD_CREATE;
__pthread_last_event = new_
/* We have to set the PID here since the callback function
in the debug library will need it and we cannot guarantee
the child got scheduled before the debugger. */
new_thread->p_pid =
/* Now call the function which signals the event. */
__linuxthreads_create_event ();
/* Now restart the thread. */
__pthread_unlock(new_thread->p_lock);
if (pid == 0)
pid = __clone(pthread_start_thread, (void **) new_thread,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
__pthread_sig_cancel, new_thread);
/* Check if cloning succeeded */
if (pid == -1) {
/* Free the stack if we allocated it */
if (attr == NULL || !attr->__stackaddr_set)
if (new_thread->p_guardsize != 0)
munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
INITIAL_STACK_SIZE);
__pthread_handles[sseg].h_descr = NULL;
__pthread_handles[sseg].h_bottom = NULL;
__pthread_handles_num--;
/* 将线程添加到__pthread_main_thread 双向链表中 由管理线程管理*/
new_thread->p_prevlive = __pthread_main_
new_thread->p_nextlive = __pthread_main_thread->p_
__pthread_main_thread->p_nextlive->p_prevlive = new_
__pthread_main_thread->p_nextlive = new_
/* Set pid field of the new thread, in case we get there before the
child starts. */
new_thread->p_pid = // 记录了clone 返回的pid
/* We're all set */
*thread = new_thread_

我要回帖

更多关于 在linux中 的文章

 

随机推荐