Linux进程与线程的比较

进程与线程的关系

在Linux 2.6以后,系统使用了一种新的pthread线程库NPTL(Native POSIX Threading Library),但其实系统底层依旧使用轻量级进程(LWP)来实现线程这一机制,所以线程与进程的关系颇为繁杂。
首先要明确的是,某一进程中的所有线程共用同一“进程id”(pid)。但为了管理不同线程对系统资源的使用,这里引入了一个“线程组编号”(tgid)的概念。其中,“主线程”的tgid即为该进程的pid。
举个例子,系统中运行着一个由两个线程组成的进程sockcli3,首先使用ps指令查看其pid:

➜ ~ ps -e | grep sockcli3
2631 pts/19 00:00:00 sockcli3

此处只显示了进程pid。然后,使用ps指令的-L参数进一步查看其线程组id:

➜ ~ ps -L 2631
PID LWP TTY STAT TIME COMMAND
2631 2631 pts/19 Sl+ 0:00 /home/ljy/build-sockcli3-unknown-Debug/sockcli3
2631 2701 pts/19 Sl+ 0:00 /home/ljy/build-sockcli3-unknown-Debug/sockcli3

可以看到,此处两线程tgid(LWP一栏)不同,pid相同,其中主线程的pid与tgid一致。

进程、线程与信号

为了区分“发送给进程的信号”和“发送给线程的信号”, task_struct里面维护了两套signal_pending,一套是线程组共享的, 一套是线程独有的。通过kill发送的信号被放在线程组共享的signal_pending中, 可以由任意一个线程来处理;通过pthread_kill发送的信号,被放在线程独有的signal_pending中,只能由指定线程来处理。

进程、线程的系统接口

进程和线程的系统接口颇为相似,总结如下,摘自《Unix环境高级编程》

进程原语线程原语描述
forkpthread_create创建新的控制流
exitpthread_exit从现有的控制流中退出
waitpidpthrread_join从控制流中得到退出状态
atexitpthrread_cancel_push注册在退出控制时调用的函数
getpidpthrread_self获取控制流的ID
abortpthrread_cancel从控制流中得到退出状态

进程、线程的终止

需要注意的是,不管是子进程/线程的外部使用了abort/pthread_cancel,还是内部使用了exit/pthread_exit/return ,操作系统依旧保留了控制流所占用的内存堆栈。毕竟父进程/主线程还需要异步处理子进程/子线程的返回值。
如果没有在控制流终止后回收其资源,会出现内存泄漏的情况。在程序长时间运行的情况下,整个程序占用的内存会持续增长。
当程序逻辑繁杂时,内存泄漏问题不易排查,毕竟编译器不会对这种问题给出提示。这时可以借助内存检查工具valgrind。
检查内存泄漏的常用语法为:

valgrind –tool=memcheck –leak-check=full ./your_program

若存在线程资源未回收的情况,会有类似如下的提示:

==9129== 288 bytes in 1 blocks are possibly lost in loss record 2 of 4
==9129== at 0x4C2FB55: calloc (vg_replace_malloc.c:711)
==9129== by 0x40138A4: allocate_dtv (dl-tls.c:322)
==9129== by 0x40138A4: _dl_allocate_tls (dl-tls.c:539)
==9129== by 0x4E4226E: allocate_stack (allocatestack.c:588)
==9129== by 0x4E4226E: pthread_create@@GLIBC_2.2.5 (pthread_create.c:539)
==9129== by 0x401DCE: MainThd::MainThd() (mainthd.cpp:16)
==9129== by 0x401B9F: main (main.cpp:5)

valgrind 会提示泄漏内存段在曾由那段代码申请,这有助于排查问题。
若觉得手动回收子控制流颇为繁琐(毕竟这涉及了同步问题),且不关心子控制流的返回值,可将线程/进程从主线程/父进程分离。此时,当子控制流结束时,主控制流不会以阻塞状态等待其完成资源回收,而是交由操作系统全权负责。
对于线程,pthread库中有如下接口:

   #include <pthread.h>
   int pthread_detach(pthread_t thread);
   int pthread_attr_setdetachstate (pthread_attr_t *__attr,
                                    int __detachstate)

至于进程,POSIX.1-2001允许将SIGCHLD的信号处理函数设置为SIG_IGN,这时子进程退出的时候将不会进入僵尸状态,并且它所占用的系统资源将被操作系统自动回收。即在该进程中绑定两信号:

signal(SIGCHLD, SIG_IGN);

参考资料:
http://www.cnblogs.com/ISeeIC/p/3617630.html
http://blog.csdn.net/u010154760/article/details/45312979
http://blog.chinaunix.net/uid-12274566-id-3043253.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值