这个主要针对进程线程的api和概念来讲的,了解了后边碰到线程同步以及进程通信从原理上就会有个认识
(一)控制原语
进程原语 | 线程原语 | 描述 |
fork | pthread_create | 创建。从创建上可以看出两者的区别,strace命令跟踪到前者调用clone,后者clone&mmap2 |
exit | pthread_exit | 退出 |
waitpid | pthread_join | 等待,并得到退出状态 |
atexit | pthread_cleanup_push | 注册退出时候调用函数 |
getpid | pthread_self | 获取控制流id |
abort | pthread_cancel | 请求非正常退出 |
pthread_detach | 线程进入分离状态,然后自动进行资源释放,不需pthread_join处理。 |
关于fork 和 pthread_create这里贴的连接可以参考一下。
http://www.fuzhijie.me/?p=235
关于pthread_join & pthread_detach刚开始看书上说明以及man page有点吃力,写了个测试就一目了然了。
/*
*线程终止测试
*pthread_exit(),pthread_join().
*分离态pthread_detach()
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* thread_handle(void* arg)
{
// pthread_detach(pthread_self()); //自己能使自己处理分离状态,之前写错了。现在修正
// sleep(4);
printf("from thread_handle\n");
return ;
// pthread_exit();
}
int main(int argc,char* argv[])
{
pthread_t tid;
int result;
void* retvar;
if( (result = pthread_create(&tid,NULL,thread_handle,NULL)) != 0)
perror("pthread create error\n");
if( (result = pthread_detach(tid)) != 0)
printf("pthread detach error\n"); \\线程中使用error_no牵扯到同步与私有化问题,之前用perror也是不当的,这里给出修正
// sleep(2);
if( (result = pthread_join(tid,&retvar)) != 0)
printf("pthread join error\n");
printf("main exit ,and thread return %d\n",(int)result);
exit(0);
}
detach之后的输出
pthread join error
main exit,and thread return xxxx //这里thread没有执行
如果sleep(2)
pthread join error
from thread handle
main exit,and thread return xxxx
(二) 系统实现浅析
系统环境
$cat /proc/version
Linux version 3.0.1 ([email protected]) (gcc version 4.4.5 (Debian 4.4.5-8) ) #1 SMP Fri Aug 12 11:50:03 CST 2011
这里我创建1000个线程和1000个进程进行跟踪截取部分。
$strace -c ./my_thread
130ms
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
97.99 0.001170 1 1011 618 mmap2
2.01 0.000024 0 382 clone
$strace -c ./my_proc
63ms
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000166 0 1000 clone
线程函数在编译的时候,需要-lpthread ,也就是说系统内核没有实现线程。
在trace 函数fork 与 pthread_create的时候,两者都是通过clone实现.fork调用的clone,pthread_create在mmap2返回错误的时候调用clone.而在网上搜到资料里fork和vfork调用的是do_fork,但是我通过trace没有跟踪到这个函数,问了个了解内核实现的同学说do_fork调用clone..好吧,不管怎么样都不影响我们对他的理解。
线程和进程在内核的系统调用的相似性上表明两者在linux下的区别,进程由系统内核实现,线程在系统调用之余其建立、销毁、同步由线程库pthread做了大量的工作。
具体的clone函数的参数的说明能更了解一下两者的概念,这里我就不继续往下深挖了。
这个帖子讨论的还很有意义,http://topic.csdn.net/u/20100514/23/a71bad9c-8c84-4e9c-aa7f-c961af943a7c.html
如果了解了线程和进程的内存布局图,对两者的认识可能更清晰一点。(进程笔记那一节我记录了进程的内存布局图)
这个图出自http://www.kaoyan.com/kaoyan/18/330074/index_6.html,因为他是概念性的介绍,可能各个系统的实现不太一样。但是大体应该也差不多,一个进程内的
多线程共享代码段、数据段(初始化&未初始化),而其堆栈段是不同的(也就是控制流)。
(三) 保留位
windows的进程与线程的关系(虽然之前做windows的开发比较多一些但是还真没有好好理解这一块,汗颜)
牵扯到信号、分离&僵尸、资源清理的一下疑问,以后补充
之前接触多线程实现都是windows下,对linux的线程与进程的认识局限在linux的进程是轻量级进程,在linux下多用多进程进行编程。而现在我的理解是linux下的进程实现确实是比windows快很多,但是其线程实现又比进程实现快很多两者实现我们也略有介绍。所以同步需要比较少 的情况下,不管是windows还是linux采用多线程还是比较好一些。对一下概念做点代码测试能使理解更立体一点:)概念上资源调度的基本单元是进程,控制调度的基本单元是线程,通过本次的代码测试对概念和实现有了新认识