Chinaunix首页 | 论坛 | 博客
  • 博客访问: 318828
  • 博文数量: 85
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 800
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-18 15:21
文章分类

全部博文(85)

文章存档

2017年(1)

2016年(19)

2015年(55)

2014年(10)

我的朋友

分类: LINUX

2015-03-22 17:27:24

一,线程常见函数介绍
[cpp] 
  1. #include  
  2. #include  
  3. void *thread_routine(void *arg)  
  4. {  
  5.     pthread_t tid=pthread_self();  
  6.     printf("thread 1 say hello\n");  
  7.     return arg;  
  8. }  
  9. int main()  
  10. {  
  11.     pthread_t thread_id;  
  12.     void * thread_result;  
  13.     int status;  
  14.     status=pthread_create(&thread_id,NULL,thread_routine,NULL);  
  15.     if(status!=0)  
  16.     {  
  17.         printf("create error\n");  
  18.         return 1;  
  19.     }  
  20.     status=pthread_join(thread_id,&thread_result);  
  21.     if(status!=0)  
  22.     {  
  23.         printf("join error\n");  
  24.         return 1;  
  25.     }  
  26.     if(thread_result==NULL)  
  27.         return 0;  
  28.     else  
  29.         return 1;  
  30. }  
首先看上面这个例子,简单的创建一个线程,在线程中打印thread 1 say hello。
首先分析上面程序涉及的函数。
1,创建线程,线程通过调用pthread_create函数来创建其他线程,原型如下:
  1. #include   
  2. typedef void*(func)(void*);  
  3. int pthread_create(pthread_t *tid, const pthread_attr_t *attr,func *f, void *arg);      若成功返回0,若出错则非0  
1.1
当pthread_create返回时,参数tid包含新创建线程的ID,新线程可以通过pthread_self函数获取自己线程的ID。
#include
pthread_t pthread_self();  

1.2 线程创建属性 
pthread_create()中的attr参数是一个结构指针,结构中的元素分别对应着新线程的运行属性,主要包括以下几项: 

__detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时 自行释放所占用的资源。缺省为pthread_CREATE_JOINABLE状态。这个属性也可以在线程创建并运行以后用 pthread_detach()来设置,而一旦设置为pthread_CREATE_DETACH状态(不论是创建时设置还是运行时设置)则不能再恢复 到pthread_CREATE_JOINABLE状态。 

__schedpolicy,表示新线程的调度策略,主要包括SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮转法)和 SCHED_FIFO(实时、先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效。运行时可以用过 pthread_setschedparam()来改变。 

__schedparam,一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR 或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0。 

__inheritsched,有两种值可供选择:pthread_EXPLICIT_SCHED和 pthread_INHERIT_SCHED,前者表示新线程使用显式指定调度策略和调度参数(即attr中的值),而后者表示继承调用者线程的值。缺省 为pthread_EXPLICIT_SCHED。 

__scope,表示线程间竞争CPU的范围,也就是说线程优先级的有效范围。POSIX的标准中定义了两个 值:pthread_SCOPE_SYSTEM和pthread_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅 与同进程中的线程竞争CPU。目前LinuxThreads仅实现了pthread_SCOPE_SYSTEM一值。 

pthread_attr_t结构中还有一些值,但不使用pthread_create()来设置。 

为了设置这些属性,POSIX定义了一系列属性设置函数,包括pthread_attr_init()、pthread_attr_destroy()和与各个属性相关的pthread_attr_get---/pthread_attr_set---函数。

1.3 线程创建的Linux实现 

        我们知道,Linux的线程实现是在核外进行的,核内提供的是创建进程的接口do_fork()。内核提供了两个系统调用__clone()和 fork(),最终都用不同的参数调用do_fork()核内API。当然,要想实现线程,没有核心对多进程(其实是轻量级进程)共享数据段的支持是不行 的,因此,do_fork()提供了很多参数,包括CLONE_VM(共享内存空间)、CLONE_FS(共享文件系统信息)、 CLONE_FILES(共享文件描述符表)、CLONE_SIGHAND(共享信号句柄表)和CLONE_PID(共享进程ID,仅对核内进程,即0号 进程有效)。当使用fork系统调用时,内核调用do_fork()不使用任何共享属性,进程拥有独立的运行环境,而使用 pthread_create()来创建线程时,则最终设置了所有这些属性来调用__clone(),而这些参数又全部传给核内的do_fork(),从 而创建的"进程"拥有共享的运行环境,只有栈是独立的,由__clone()传入。  

        Linux线程在核内是以轻量级进程的形式存在的,拥有独立的进程表项,而所有的创建、同步、删除等操作都在核外pthread库中进行。pthread 库使用一个管理线程(__pthread_manager(),每个进程独立且唯一)来管理线程的创建和终止,为线程分配线程ID,发送线程相关的信号 (比如Cancel),而主线程(pthread_create())的调用者则通过管道将请求信息传给管理线程。 

2,回收终止线程的资源

缺省为pthread_CREATE_JOINABLE状态,上面的程序采用默认设置,即需要线程通过调用pthread_join函数等待其他线程终止
  1. #include   
  2. int pthread_join(pthread_t tid,void **thread_retrun);  若成功返回0,出错则非零  
pthread_join函数会阻塞,直到线程tid终止,然后回收已终止线程占用的所有存储器资源。
除此还要熟悉一下几个函数
  1. #include   
  2. int pthread_detach(pthread_t tid);   
  1. int pthread_exit(void*thread_return);  
  1. int pthread_cancel(pthread_t);    

pthread_detach()函数
    用于指示应用程序在线程tid终止时回收其存储空间。如果tid尚未终止,pthread_detach()不会终止该线程。

一个线程是以一下方式之一来终止的:当顶层的线程例程返回时,线程会隐式的终止;通过调养pthread_exit函数显式的终止,该函数返回一个 指向thread_return的指针。如果主线程调用pthread_exit,它会等待所有其他对等线程终止,然后再终止主线程和整个进程,返回值为 thread_return。对等线程也可以调用pthread_cancel来终止当前线程。

二,线程的生命周期

通常将线程的状态分为以下几种:就绪,运行,阻塞,终止,状态转移图如下所示。

线程的创建,上例中status=pthread_create(& thread_id,NULL,thread_routine,NULL);完成线程的创建工作,线程创建注意:pthread_create函数返回同 线程执行之间没有同步关系,被创建之后进入就绪状态。线程启动,即开始执行pthread_routine函数。通常线程在以下情况被阻塞:试图加锁一个 已经锁住的互斥量;等待某个条件变量;执行无法立即完成的I/O操作。程序中pthread_join函数处阻塞,等待它创建的线程结束。线程终止,本例 中线程pthread_routine线程资源在pthread_join函数返回时被回收。而pthread_detach分离的线程在线程结束时自动 被回收。



阅读(936) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~