EDU511 国际专业IT教育服务门户
设为首页   加入收藏    联系我们
寻找IT教育内容合作伙伴
招聘教育网络编辑和运营门户高手
中讯IT教育2008年改版上线
寻找地方站运营伙伴QQ:59955917
中讯IT 技术成就未来
   你现在的位置:首页 >> 新闻系统 >> 操作系统 >> Solaris >> Solaris高级教程 >> 正文

Solaris2.4 多线程编程指南2--用多线程编程

 
 
日期:08-06-02 22:40:38 点击: 来源:中讯IT
 
2 用多线程编程

2.1线程(函数)库(The Threads Library)

用户级多线程是通过线程库,libthread来实现的(参考手册第3页: library routines)。线程库支持信号,为可运行的程序排队,并负责同 时操纵多任务。
这一章讨论libthread中的一些通用过程,首先接触基本操作,然后循 序渐进地进入更复杂的内容。
创建线程-基本特性 Thr_create(3T)
获得线程号 Thr_self(3T)
执行线程 Thr_yield(3T,the below is same)
挂起或继续线程 Thr_suspend
Thr_continue
向线程送信号 Thr_kill
设置线程的调用掩模 Thr_sigsetmask
终止线程 Thr-exit
等待线程终止 Thr-join
维护线程的私有数据 Thr_keycreate
Thr_setspecific
Thr_getspecific
创建线程-高级特性 Thr_create
获得最小堆栈容量 Thr_min_stack
获得或设置线程的同时性等级 Thr_getconcurrency
Thr_setconcurrency
获得或设置线程的优先级 Thr_getprio
Thr_setprio

2.1.1创建线程-基本篇

thr_create过程是线程库所有过程当中最复杂的一个。这部分的内容仅适用于你使用thr_create的缺省参数来创建进程。
对于thr_create更加复杂的使用,包括如何使用自定参数,我们将在高级特性部分给出说明。
thr_create(3T)
这个函数用于在当前进程中添加一个线程。注意,新的线程不继承未处理的信号,但继承优先级和信号掩模。
#include
int thr_create(void *stack_base,size_t stack_size,
void *(*start_routine) (void*),void *arg,long flags,
thread_t *new_thread);
size_t thr_min_stack(void);
stack_base--新线程的堆栈地址。如果stack_base是空则thr_create()按 照stack_size为新线程分配一个堆栈。
Stack_size--新线程堆栈的字节数。如果本项为0,将使用缺省值,一般 情况下最好将此项设为0。并不是每个线程都需要指定堆栈空间。线程库为每个线程的堆栈分配1M 的虚拟内存,不保留交换空间。(线程库用mmap(2)的MAP_NORESERVE的选项 来实现这种分配)。
Start_routine--指定线程开始执行的函数。如果start_routine返回, 线程将用该函数的返回值作为退出状态而退出。(参考thr_exit(3T))。
Flags--指定新线程的属性,一般设置为0。
Flags的值是通过下列内容的位同或来实现的(最后四个flags在高级特性中给出)。
1. THR_DETACHED 将新线程分离,使得它的线程号和其他资源在线程 结束时即可以回收利用。当你不想等待线程终止时,将其置位。如果没有明确的 同步需求阻碍,一个不挂起的,分离的线程可以在创建者的thr_create返回之前 终止并将其线程号分配给一个心得线程。
2. THR_SUSPENDED挂起新线程,直到被thr_continue唤醒。
3. THR_BOUND把新线程永久绑定在一个LWP上(生成一个绑定线程)。
4. THR_NEW_LWP将非绑定线程的同时性级别加1。
5. THR_DAEMON新线程为一个守护线程。
New_thread--指向存储新线程ID的地址。多数情况下设置为0。
Return Values--thr_create()在成功执行后返回0并退出。任何其他返回值表明有错误发生。当以下情况被检测到时,thr_create()失败并返回响应的值。
EAGAIN :超出了系统限制,例如创建了太多的LWP。
ENOMEM:可用内存不够创建新线程。
EINVAL:stack_base不是NULL而且stack_size比thr_minstack()函数返回的最小堆栈要小。

2.1.2获取线程号

thr_self(3T) 获得自身的线程号。
#include
thread_t thr_self(void)
返回值--调用者的线程号。

2.1.3放弃执行

thr_yield(3T)
thr_yield停止执行当前线程,将执行权限让给有相同或更高优先权的线程。
#include
void thr_yield(void);

2.1.4挂起或继续执行线程

thr_suspend(3T) 挂起线程。
#include
int thr_suspend(thread_t target_thread);
thr_suspend()立即挂起由target_thread指定的线程。在thr_suspend成功返回后,挂起的线程不再执行。后继的thr_suspend无效。
Return Values--执行成功后返回0。其他返回值意味着错误。以下情况发生时,thr_suspend()失败并返回相关值。
ESRCH: 在当前进程中找不到target_thread。

Thr_continue(3T)
Thr_continue()恢复执行一个挂起的线程。一旦线程脱离挂起状态,后继的
thr_continue将无效。
#include
int thr_continue(thread_t target_thread);
一个挂起的线程不会被信号唤醒。信号被挂起知道线程被thr-continue恢复执行。
返回值--成功执行后返回0。其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
ESRCH:target_thread在当前进程中找不到。

2.1.5向线程发信号

thr_kill(3T)向线程发信号
#include
#include
int thr_kill(thread_t target_thread,int sig);
thr_kill向线程号为target_thread的线程发送信号sig。Target_thread一定要与调用线程处于同一个进程内。参数sig一定是signal(5)中定义过的。
当sig是0时,错误检查将被执行,没有实际的信号被发送。这可以用来检测arget_thread参数是否合法。
返回值--成功执行后返回0,其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
EINVAL:sig非法;
ESRCH:target_thread找不到;

2.1.6设置本线程的信号掩模

thr_sigsetmask(3T) 获取或改变本线程的信号掩模(signal mask)
#include
#include
int thr_sigsetmask(int how,const sigset_t *set,sigset_t *oset);
how参数决定信号设置将被如何改变,可以是下列值之一:
SIG_BLOCK--在当前信号掩模上增加set,set指要阻塞的信号组。
SIG_UNBLOCK--在当前信号掩模上去掉set,set指要解除阻塞的信号组。
SIG_SETMASK--用新的掩模代替现有掩模,set指新的信号掩模。
当set的值是NULL时,how的值并不重要,信号掩模将不被改变。所以,要查询当前的信号掩模,就给set赋值为NULL。
当参数oset不是NULL时,它指向以前的信号掩模存放的地方。
Return Values--正常执行后返回0。其他值意味着错误。在以下情况发生时, 函数失败并返回相关值。
EINVAL:set不是NULL且how没有被定义;
EFAULT:set或oset不是合法地址;

2.1.7终止线程

thr_exit(3T)
用来终止一个线程。
#include
void thr_exit(void *status);
thr_exit 函数终止当前线程。所有的私有数据被释放。如果调用线程不是一个分离线程,线程的ID和返回状态保留直到有另外的线程在等待。否则返回状态被忽略,线程号被立刻重新使用。
返回值--当调用线程是进程中的最后一个非守护线程,进程将用状态0退出。 当最初的线程从main()函数中返回时进程用该线程main函数的返回值退出。
线程可以通过两种方式停止执行。第一种是从最初的过程中返回。第二种是 提供一个退出代码,通过调用thr_exit()结束。下面的事情依赖于在线程创建时 flags的设置。
线程A终止的缺省操作(当flags的相应位设为0时,执行缺省操作)是保持 状态,直到其它线程(不妨设为B)通过"联合"的方式得知线程A已经死亡。联合 的结果是B线程得到线程A的退出码,A自动消亡。你可以通过位或来给flags的 THR_DETACHED参数置位,使得线程在thr_exit()之后或从最初过程返回后立即消 亡。在这种情况下,它的退出码不会被任何线程获得。
有一个重要的特殊情况,在主线程--即最初存在的线程--从主函数返回或调 用了exit(),整个进程将终止。所以在主线程中要注意不要过早地从主函数main 返回。
如果主线程仅仅调用了thr_exit(),仅仅是它自己死亡,进程不会结束,进 程内的其他线程将继续运行(当然,如果所有的线程都结束,进程也就结束了)。
如果一个线程是非分离的,在它结束后一定要有其它进程与它"联合",否则 该线程的资源就不会被回收而被新线程使用。所以如果你不希望一个线程被 "联合",最好按照分离线程来创建。
另外一个flag参数是THR_DAEMON。使用这个标志创建的线程是守护线程,在 其他线程终止之后,这些线程自动终止。这些守护线程在线程库内部特别有用。 守护线程可以用库内函数创建--在程序的其他部分是不可见的。当程序中所 有的其他线程终止,这些线程自动终止。如果它们不是守护线程,在其它线程终 止后他们不会自动终止,进程不会自动结束。

2.1.8等待线程结束

thr_join(3T) 用thr_join函数来等待线程终止。
#include
int thr_join(thread_t wait_for,thread_t *departed,void **status);
thr_join()函数阻塞自身所在的线程,直到由wait_for指定的线程终止。指 定的线程一定与本线程在同一个进程内部,而且一定不是分离线程。当wait_for 参数为0时,thr
 
责任编辑:
 
前一篇:
后一篇:
相关新闻(文章)

登录模块加载中...
热点操作系统技术
友情链接
重庆之窗 | 重庆IT教育 | 我爱论文网 | 涪陵课件园 | 中国教育导航 | 第一教育网 | 中华IT培训网 
百度网址大全   重庆电脑维修网   华育国际教育 maple story   中国销售培训网    更多友情链接>>>
地址:重庆渝中区大坪正街88号 Copyright © edu511.com All rights reserved.
本站建设得到北京泰胜得风险投资机构、重庆网通信息港、平全教育服务中心与的大力支持            重庆视网科技发展有限公司版权所有 邮编:400041
电话:023-61630611 15902314551            ICP备案号:渝ICP备08002346号 QQ:59955917       邮箱:sysium_yuh@126.com yuhong@edu511.com