首先,得到一个唯一的键值,mywin_key。此键用于标识线程特定数据类。第一个调用 make_mywin() 的线程最终会调用 pthread_key_create(),该函数将唯一的 key 赋给其第一个参数。第二个参数是 destructor 函数,用于在线程终止后将该线程的特定于该线程的数据项实例解除分配。 接下来为调用方的线程特定数据项的实例分配存储空间。获取已分配的存储空间,调用 create_window(),以便为该线程设置时限。win 指向为该时限分配的存储空间。最后,调用 pthread_setspecific(),将 win 与该键关联。 以后,每当线程调用 pthread_getspecific() 以传递全局 key,线程都会获得它在前一次调用 pthread_setspecific() 时设置的与该键关联的值)。 线程终止时,会调用在 pthread_key_create() 中设置的 destructor 函数。每个 destructor 函数仅在终止线程通过调用 pthread_setspecific() 为 key 赋值之后才会被调用。 获取线程标识符请使用 pthread_self(3C) 获取调用线程的 thread identifier。 pthread_self 语法pthread_t pthread_self(void); #include <pthread.h>
pthread_t tid;
tid = pthread_self(); pthread_self 返回值pthread_self() 返回调用线程的 thread identifier。 比较线程 ID请使用 pthread_equal(3C) 对两个线程的线程标识号进行比较。 pthread_equal 语法int pthread_equal(pthread_t tid1, pthread_t tid2); #include <pthread.h>
pthread_t tid1, tid2;
int ret;
ret = pthread_equal(tid1, tid2); pthread_equal 返回值如果 tid1 和 tid2 相等,pthread_equal() 将返回非零值,否则将返回零。如果 tid1 或 tid2 是无效的线程标识号,则结果无法预测。 初始化线程使用 pthread_once(3C),可以在首次调用 pthread_once 时调用初始化例程。以后调用 pthread_once() 将不起作用。 pthread_once 语法int pthread_once(pthread_once_t *once_control,
void (*init_routine)(void)); #include <pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int ret;
ret = pthread_once(&once_control, init_routine); once_control 参数用来确定是否已调用相关的初始化例程。 pthread_once 返回值pthread_once() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_once() 将失败并返回相应的值。 EINVAL
描述: once_control 或 init_routine 是 NULL。
停止执行线程使用 sched_yield(3RT),可以使当前线程停止执行,以便执行另一个具有相同或更高优先级的线程。 sched_yield 语法int sched_yield(void); #include <sched.h>
int ret;
ret = sched_yield(); sched_yield 返回值sched_yield() 在成功完成之后返回零。否则,返回 -1,并设置 errno 以指示错误状态。 ENOSYS
描述: 本实现不支持 sched_yield。
设置线程的优先级请使用 pthread_setschedparam(3C) 修改现有线程的优先级。此函数对于调度策略不起作用。 pthread_setschedparam 语法int pthread_setschedparam(pthread_t tid, int policy,
const struct sched_param *param); #include <pthread.h>
pthread_t tid;
int ret;
struct sched_param param;
int priority;
/* sched_priority will be the priority of the thread */
sched_param.sched_priority = priority;
policy = SCHED_OTHER;
/* scheduling parameters of target thread */
ret = pthread_setschedparam(tid, policy, ¶m); pthread_setschedparam 返回值pthread_setschedparam() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_setschedparam() 函数将失败并返回相应的值。 EINVAL
描述: 所设置属性的值无效。
ENOTSUP
描述: 尝试将该属性设置为不受支持的值。
获取线程的优先级pthread_getschedparam(3C) 可用来获取现有线程的优先级。 pthread_getschedparam 语法int pthread_getschedparam(pthread_t tid, int policy,
struct schedparam *param); #include <pthread.h>
pthread_t tid;
sched_param param;
int priority;
int policy;
int ret;
/* scheduling parameters of target thread */
ret = pthread_getschedparam (tid, &policy, ¶m);
/* sched_priority contains the priority of the thread */
priority = param.sched_priority; pthread_getschedparam 返回值pthread_getschedparam() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。 ESRCH
描述: tid 指定的值不引用现有的线程。
向线程发送信号请使用 pthread_kill(3C) 向线程发送信号。 pthread_kill 语法int pthread_kill(thread_t tid, int sig); #include <pthread.h>
#include <signal.h>
int sig;
pthread_t tid;
int ret;
ret = pthread_kill(tid, sig); pthread_kill() 将信号 sig 发送到由 tid 指定的线程。tid 所指定的线程必须与调用线程在同一个进程中。sig 参数必须来自 signal(5) 提供的列表。 如果 sig 为零,将执行错误检查,但并不实际发送信号。此错误检查可用来检查 tid 的有效性。 pthread_kill 返回值pthread_kill() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_kill() 将失败并返回相应的值。 EINVAL
描述: sig 是无效的信号量。
ESRCH
描述: 当前的进程中找不到 tid。
访问调用线程的信号掩码请使用 pthread_sigmask(3C) 更改或检查调用线程的信号掩码。 pthread_sigmask 语法int pthread_sigmask(int how, const sigset_t *new, sigset_t *old); #include <pthread.h>
#include <signal.h>
int ret;
sigset_t old, new;
ret = pthread_sigmask(SIG_SETMASK, &new, &old); /* set new mask */
ret = pthread_sigmask(SIG_BLOCK, &new, &old); /* blocking mask */
ret = pthread_sigmask(SIG_UNBLOCK, &new, &old); /* unblocking */ how 用来确定如何更改信号组。how 可以为以下值之一: SIG_BLOCK。向当前的信号掩码中添加 new,其中 new 表示要阻塞的信号组。 SIG_UNBLOCK。从当前的信号掩码中删除 new,其中 new 表示要取消阻塞的信号组。 SIG_SETMASK。将当前的信号掩码替换为 new,其中 new 表示新的信号掩码。
当 new 的值为 NULL 时,how 的值没有意义,线程的信号掩码不发生变化。要查询当前已阻塞的信号,请将 NULL 值赋给 new 参数。 除非 old 变量为 NULL,否则 old 指向用来存储以前的信号掩码的空间。 pthread_sigmask 返回值pthread_sigmask() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_sigmask() 将失败并返回相应的值。 EINVAL
描述: 未定义 how 的值。
安全地 Fork请参见解决方案: pthread_atfork中有关 pthread_atfork(3C) 的论述。 pthread_atfork 语法int pthread_atfork(void (*prepare) (void), void (*parent) (void),
void (*child) (void) ); pthread_atfork 返回值pthread_atfork() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_atfork() 将失败并返回相应的值。 ENOMEM
描述: 表空间不足,无法记录 Fork 处理程序地址。
终止线程请使用 pthread_exit(3C) 终止线程。 pthread_exit 语法void pthread_exit(void *status); #include <pthread.h>
void *status;
pthread_exit(status); /* exit with status */ pthread_exit() 函数可用来终止调用线程。将释放所有线程特定数据绑定。如果调用线程尚未分离,则线程 ID 和 status 指定的退出状态将保持不变,直到应用程序调用 pthread_join() 以等待该线程。否则,将忽略 status。线程 ID 可以立即回收。有关线程分离的信息,请参见设置分离状态。 pthread_exit 返回值调用线程将终止,退出状态设置为 status 的内容。 结束线程可通过以下方法来终止执行: 从线程的第一个(最外面的)过程返回,使线程启动例程。请参见 pthread_create。 调用 pthread_exit(),提供退出状态。 使用 POSIX 取消函数执行终止操作。请参见 pthread_cancel()。
线程的缺省行为是拖延,直到其他线程通过 "joining" 拖延线程确认其已死亡。此行为与非分离的缺省 pthread_create() 属性相同,请参见 pthread_detach。join 的结果是 joining 线程得到已终止线程的退出状态,已终止的线程将消失。 有一个重要的特殊情况,即当初始线程(即调用 main() 的线程)从 main() 调用返回时或调用 exit() 时,整个进程及其所有的线程将终止。因此,一定要确保初始线程不会从 main() 过早地返回。 请注意,如果主线程仅仅调用了 pthread_exit,则仅主线程本身终止。进程及进程内的其他线程将继续存在。所有线程都已终止时,进程也将终止。 取消线程取消操作允许线程请求终止其所在进程中的任何其他线程。不希望或不需要对一组相关的线程执行进一步操作时,可以选择执行取消操作。 取消线程的一个示例是异步生成取消条件,例如,用户请求关闭或退出正在运行的应用程序。另一个示例是完成由许多线程执行的任务。其中的某个线程可能最终完成了该任务,而其他线程还在继续运行。由于正在运行的线程此时没有任何用处,因此应当取消这些线程。 |