摘要:在使用多线程程序时,有时会遇到程序功能异常的情况,而这种异常情况并不是每次都发生,很难模拟出来。这时就需要运用在程序运行时跟踪线程的手段,而linux系统的LWP和strace命令正是这种技术手段。本文对LWP和strace命令做了简明扼要的介绍,并通过一个实例来说明如何运用。总而言之,LWP和strace的使用可以提高多线程程序的可维护性。

问题描述:

我们来看一个问题:程序tcp_client同时创建多个线程向同一个服务器发送数据,每个线程发送不同类型的数据,服务器接收数据后,可以通过界面查看到多个数据在刷新。程序运行一段时间后,突然出现只有某个类型的数据不刷新,其他数据刷新正常,但是服务端客户端程序都没有报错。这时我们该怎么办?

很明显,这时程序调试者需要知道不刷新线程的线程ID,然后通过某种手段查看该线程为何出现了异常。通过linux的ps -eLF|grep pid命令可以查看进程的线程ID(LWP号),但是问题在于如果我们没有在创建线程时记录其线程ID,我们仍然无法得知哪个LWP号是我们想要追踪的。

我们来看一下LWP号是什么,以及如何在创建线程时记录每个线程的LWP号。

pthread_create是基于clone实现的, 创建出来的其实是进程, 但这些进程与父进程共享很多东西,

共享的东西都不用复制给子进程, 从而节省很多开销, 因此,这些子进程也叫轻量级进程(light-weight process)简称LWP. 每个LWP都会与一个内核线程绑定, 这样它就可以作为独立的调度实体参与cpu竞争.

LWP被pthread封装后, 以线程面目示人, 它有自己的id, 这里要区分 phtread_create

给LWP分配的id, 和操作系统给LWP分配的进程id. 这两者是不同的, 前者用于标志线程,可以暴露给

用户, 后者其实就是进程的id, 它没有暴露出来, 必须通过系统调用来得到.

获取LWP的方法是通过syscall系统调用(具体说明参加man手册),下面是一个例子程序:

#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <pthread.h> //线程处理函数,输出LWP号
void *func(void *argv)
{
    //获取LWP的方法1
    int lwp;
    lwp = syscall(__NR_gettid);
    printf("lwp[%d]\n", lwp);
    
    //获取LWP的方法2
    int lwp2;
    lwp2 = syscall(SYS_gettid);
    printf("lwp2[%d]\n", lwp2);
    sleep(50);
} int main(void)
{
    pthread_t thd;
    pthread_create(&thd, NULL, func, NULL); //创建线程
    sleep(60);
    return 0;
}

在获取LWP号以后,接下来就是通过strace命令对线程进行追踪了。

strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通 过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

在理想世界里,每当一个程序不能正常执行一个功能时,它就会给出一个有用的错误提示,告诉你在足够的改正错误的线索。但遗憾的是,我们不是生活在理想世界 里,起码不总是生活在理想世界里。有时候一个程序出现了问题,你无法找到原因。这就是调试程序出现的原因。strace是一个必不可少的 调试工具,strace用来监视系统调用。你不仅可以调试一个新开始的程序,也可以调试一个已经在运行的程序(把strace绑定到一个已有的PID上 面)。

strace的参数有很多,常见的参数介绍如下:

-o filename  将strace的输出写入文件filename

-p pid      跟踪指定的进程pid.

-t   在输出中的每一行前加上时间信息.

-tt  在输出中的每一行前加上时间信息,微秒级.

-T   显示每一调用所耗的时间.

-f   跟踪由fork调用所产生的子进程.

-ff  如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程     号.

举个例子:我们对tcp_client程序做一个小小的改动,在通过pthread_create创建线程后,每个线程里都通过syscall函数记录其LWP号,同时记录该LWP号对应的数据类型。如果程序再次出现文章开头时提到的异常状况,这时我们可以通过“strace -o tcp_client.txt -tt -p 欲追踪的LWP号”,这样就很快就能知道发生异常的线程在做哪些系统调用了。

总结:在设计程序的时候,一定要考虑将来的维护问题。对于多线程程序,其调试会更加困难,通过在创建线程中记录LWP号和对应的线程功能,可以为以后的调试提供很大帮助。

参考文章:

1、关于Linux的进程和线程

http://kenby.iteye.com/blog/1014039

2、linux strace命令:

http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html

本文出自 “篮彩大神” 博客,请务必保留此出处http://lancaidashen.blog.51cto.com/11086793/1734196

linux跟踪线程的方法:LWP和strace命令的更多相关文章

  1. inux跟踪线程的方法:LWP和strace命令

    摘要:在使用多线程程序时,有时会遇到程序功能异常的情况,而这种异常情况并不是每次都发生,很难模拟出来.这时就需要运用在程序运行时跟踪线程的手段,而linux系统的LWP和strace命令正是这种技术手 ...

  2. 使用 Linux 的 strace 命令跟踪/调试程序的常用选项

    原文:http://linoxide.com/linux-command/linux-strace-command-examples/作者: Raghu 在调试的时候,strace能帮助你追踪到一个程 ...

  3. Linux posix线程库总结

    由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 线程的实现,经历了如下发展阶段: Linu ...

  4. Linux编程---线程

    首先说一下线程的概念.事实上就是运行在进程的上下文环境中的一个运行流.普通进程仅仅有一条运行流,可是线程提供了多种运行的路径并行的局面. 同一时候,线程还分为核心级线程和用户级线程.主要差别在属于核内 ...

  5. Linux查看线程

    我的程序在其内部创建并执行了多个线程,我怎样才能在该程序创建线程后监控其中单个线程?我想要看到带有它们名称的单个线程详细情况(如,CPU/内存使用率). 线程是现代操作系统上进行并行执行的一个流行的编 ...

  6. 嵌入式linux应用程序调试方法

    嵌入式linux应用程序调试方法 四 内存工具 五 C/C++代码覆盖.性能profiling工具 四 内存工具 您肯定不想陷入类似在几千次调用之后发生分配溢出这样的情形. 许多小组花了许许多多时间来 ...

  7. Linux中线程使用详解

    线程与进程为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题. 使用多线程的理由之一是和进程相比,它是一种非常"节俭&qu ...

  8. Linux内核线程之深入浅出【转】

    转自:http://blog.csdn.net/yiyeguzhou100/article/details/53126626 [-] 线程和进程的差别 线程的分类 1     内核线程 2     轻 ...

  9. linux系统——线程

    linux系统线程 1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个 ...

随机推荐

  1. 【hihocoder 1122】二分图二•二分图最大匹配之匈牙利算法

    [Link]:https://hihocoder.com/problemset/problem/1122 [Description] [Solution] 二分图匹配,匈牙利算法模板题; 这里我先把染 ...

  2. Linux "零拷贝" sendfile函数中文说明及实际操作分析

    Sendfile函数说明 #include ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); sendfile ...

  3. mac自己定义tree命令

    编辑文件: vim ~/.bash_profile 在文件末尾追加: alias tree="find . -print | sed -e 's;[^/]*/;|____;g;s;____| ...

  4. js---26组合模式

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  5. [51Nod]NOIP2018提高组省一冲奖班模测训练(四)翻车记+题解

    链接 下午5点的时候,突然想起来有这个比赛,看看还有一个小时,打算来AK一下,结果因为最近智商越来越低,翻车了,我还是太菜了.上来10分钟先切掉了C和A,结果卡在了B题,唉. A.砍树 一眼题,两遍树 ...

  6. Git提交.net项目的小问题

    今天早上写了点关于asp.net core授权的东西,输入git add .的时候出现的报错 $ git add .error: open(".vs/DOTNETAuthorization/ ...

  7. numpy_basic2

    # 六.numpy的常用函数 1. 读取文件 逻辑上可被解释为二维数组的文本文件: 数据项1<分隔符>数据项2<分隔符>...<分隔符>数据项n numpy.loa ...

  8. 【AIM Tech Round 4 (Div. 2) C】Sorting by Subsequences

    [链接]http://codeforces.com/contest/844/problem/C [题意] 水题,没有记录意义 [题解] 排序之后,记录每个数字原来在哪里就好. 可以形成环的. 环的个数 ...

  9. phoenixframe自己主动化平台在Linux环境下运行用例的说明

    phoenixframe自己主动化平台支持在Linux环境下使用phantomjs,Firefox.chrome运行測试用例.但有下面几个问题须要注意: 1.若无法启动phantomjs,Firefo ...

  10. 40.【IntelliJ IDEA】使用idea解决新建jsp文件而找不到jsp文件模版的新建选项

    转自:https://www.cnblogs.com/sxdcgaq8080/p/7676294.html 使用idea解决新建jsp文件而找不到jsp文件模版的新建选项,这样每次创建一个新的jsp文 ...