Solaris2.4 多线程编程指南6--编译和调试

 

BBS水木清华站∶精华区

发信人: Mccartney (coolcat), 信区: Unix 
发信站: BBS 水木清华站 (Sun May 17 16:33:41 1998) 
 
6 编译和调试 
 
    本章描述了怎样编译和调试多线程程序。 
        编译一个多线程应用程序 
        调试一个多线程应用程序 
 
6.1编译一个多线程应用程序 
 
6.1.1使用C编译器 
 
    确认你拥有如下软件,否则将无法正常编译和连接多线程程序 
        · 头文件:thread.h errno.h 
        · 标准C编译器 
        · 标准Solaris连接器 
        · 线程库(libthread) 
        · MT-Safe库(libc, libm, libw, libintl, libmalloc,  
                libmapmalloc, libnsl, 等等) 
 
6.1.2用替代(_REENTRANT)标志进行编译 
 
    在编译多线程程序时使用"-D _REENTRANT"标志。 
    这个标志必须在编译应用程序的每一个模块时都使用。如果没有这个标志,将 
使用errno, stdio等等的旧的定义。如果要编译一个单线程应用程序,不要使用这 
个标志。 
 
*新旧连接需要小心 
 
    表6-1显示了多线程目标代码模块与旧的代码模块连接时需要非常慎重。 
        表6-1 在编译多线程程序时使用"-D _REENTRANT"标志 
文件类型                编译            参考            返回 
旧的目标文件(非线程版)和新的目标文件  没有 "-D _REENTRANT" 标志。     静态储存        传统的errno 
新的目标文件    有 "-D _REENTRANT"标志。        __errno,新的二进制入口 线程定义errno的地址 
用libnsl 里的TLI编程    有 "-D _REENTRANT"标志(必须)。        __t_errno,一个新的入口 线程定义t_errno的地址 
 
6.1.3使用libthread 
 
    为了在连接时使用libthread,需要在ld命令行里,-lc参数之前,指定 
-lthread,或者在cc 命令行的最后指定。 
    如果应用程序没有连接libthread,则对该库中的函数调用不产生实际操作。 
    Libc定义libthread为空过程。???真正的过程是在应用程序既连接libc也 
连接libthread时由libthread加入的。 
    如果一个ld命令行包含了以下的字段:.o's ... -lc -lthread ...,则C函数 
库的行为没有被定义。??? 
    不要在单线程程序中使用-lthread。这样做将在连接时建立多线程机制,在运 
行时将被初始化。这样做不但浪费资源,而且在调试中会对运行结果有不正确的显示。 
 
6.1.4使用非C的编译器 
 
    线程库使用libc中的如下内容: 
· 系统调用包装器(system call wrappers) 
· 用来显示出错信息的调用(通常是printf) 
· 运行时的连接支持来解析符号(因为库是动态连接的) 
 
    你也可以写自己的系统调用包装器和自己的printf函数,并且在连接时(而不 
是在运行时)进行符号解析,这样可以消除对libc的依赖。 
    如果线程使用应用程序提供的堆栈,则线程库不使用动态分配内存的办法。 
Thr_create(3T)函数可以由应用程序指定自己的堆栈。 
 
6.2调试多线程应用程序 
 
6.2.1一般的疏漏 
        以下列出可以导致多线程出错的常见疏漏: 
· 给新线程传递参数时使用局部或全局变量 
· 在没有同步机制的保护下访问全局内存 
· 两个线程以不同的顺序去申请两个资源导致死锁(两个线程各自占有一个资源 
并相执不下) 
· 在同步保护中有隐藏的漏洞。例如可能有如下情况:一个有同步机制(例如互斥 
锁)保护的代码段包含一个先释放再重新获得同步机制的函数调用,结果是全局内存 
实际上没有得到保护。 
· 有隐匿的,重复或递归的大自动数组的使用可能导致问题,因为多线程程序的堆 
栈容量比单线程程序有更多的限制。 
· 指定的堆栈空间不够。 
· 没有通过线程库的调用指定堆栈。 
    注意,多线程程序(特别是有错误的)经常在相同输入的情况下得到不同的结 
果,因为线程调度的顺序不同。 
    一般的,多线程bug具有统计性,而不是确定性。在调试时,跟踪的办法将会比 
设断点的办法好些。 
 
6.2.2使用adb 
 
    如果你在一个多线程程序当中绑定所有线程,一个线程和一个LWP是同步的。然 
后你通过如下支持多线程编程的adb命令访问每一个线程。 
 
表6-2 MT adb命令 
------------------------------------- 
pid:A                   绑定在进程pid上,这将停止进程及其所有LWP 
R                      与进程分离,这将恢复进程及其所有LWP 
$L                      显示在(停止的)进程中所有的活动的LWP 
n:l                     将焦点切换到第n号LWP 
$l                      显示当前焦点所在的LWP 
num:i                   忽略信号码为num的信号 
 
6.2.3使用dbx 
 
    使用dbx,可以调试和执行用C++, ANSI C, FORTRAN和PASCAL的源程序。Dbx使 
用与SPARCworks? Debugger相同的命令,但使用标准终端(tty)接口。Dbx和 
SPARCworks Debugger现在都支持多线程程序。 
    要得到dbx和Debugger的全面认识,请参考SunPro dbx(1) man page和 
《Debugging a Program》用户指南。 
    以下的dbx选项支持多线程。 
        表6-3 给MT程序使用的dbx选项 
Cont at line[sig signo id]      在信号signo发生时继续执行第line行。 
                                参见dbx的命令语言的循环控制里的continue。 
                                如果有id参数,则指定继续哪一个线程或LWP。 
                                缺省设置为all。 
Lwp                             显示当前LWP。切换到给定LWP[lwpid] 
Lwps                            列出当前进程的所有LWP 
Next … tid                     单步执行指定线程。如果一个函数调用被跳过, 
                                所有的LWP在该函数调用期间重新开始???非 
                                活动线程不能被单步执行 
Next … lid                     单步执行指定LWP。在跳过函数时并不隐含地恢 
                                复所有的LWP。在该LWP上的线程是活动的。 
Step … tid                     单步执行指定线程。如果一个函数调用被跳过, 
                                所有的LWP在该函数调用期间重新开始???非 
                                活动线程不能被单步执行 
Step … lid                     单步执行指定LWP。在跳过函数时并不隐含地恢 
                                复所有的LWP。 
Stepi … lid                    指定的LWP 
Stepi … tid                    在LWP上的线程是活动的。 
Thread                          显示当前线程。切换到线程tid。在以下情况中, 
                                一个可选的tid指当前线程。 
Thread -info[tid]               打印指定线程的所有已知情况。 
Thread -locks[tid]              打印被指定线程控制的所有锁 
Thread -suspend[tid]            把指定线程置于挂起状态。 
Thread -continue[tid]           使指定线程退出挂起状态。 
Thread -hide[tid]               隐藏指定(或当前)线程,在普通线程列表中 
                                将不被显示出来 
Thread -unhide [tid]            解除指定线程的隐藏状态 
Allthread-unhide                解除所有线程的隐藏状态 
Threads                         打印已知线程的列表 
Threads-all                     打印所有线程(包括通常不被打印的,zombies) 
All|filterthreads-mode          控制threads命令打印所有线程还是有选择地列表 
Auto|manualthreads-mode         使在GUI界面里线程监控器(Thread Inspector) 
                                线程列表得以自动更新 
Threads -mode                   显示当前模式。Any of the previous forms  
                                can be followed by a 
thread or LWP ID to get the traceback for the specified entity. 
 
-- 
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: sys11.cic.tsing] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值