APUE学习(五):线程与进程(API与概念部分)

来源:互联网 发布:mysql建立表 编辑:程序博客网 时间:2024/04/30 19:24

这个主要针对进程线程的api和概念来讲的,了解了后边碰到线程同步以及进程通信从原理上就会有个认识

(一)控制原语

进程&线程控制原语比较进程原语线程原语描述forkpthread_create创建。从创建上可以看出两者的区别,strace命令跟踪到前者调用clone,后者clone&mmap2exitpthread_exit退出waitpidpthread_join等待,并得到退出状态atexitpthread_cleanup_push注册退出时候调用函数getpidpthread_self获取控制流idabortpthread_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 (root@debian-T410) (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_thread130ms% 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_proc63ms% 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采用多线程还是比较好一些。对一下概念做点代码测试能使理解更立体一点:)概念上资源调度的基本单元是进程,控制调度的基本单元是线程,通过本次的代码测试对概念和实现有了新认识


原创粉丝点击