分享

Linux多线程pthread

 angelbrian 2011-07-19
1. Linux线程的发展

  早在LINUX2.2内核中。并不存在真正意义上的线程,当时Linux中常用的线程pthread实际上是通过进程来模拟的,也就是同过 fork来创建“轻”进程,并且这种轻进程的线程也有个数的限制:最多只能有4096和此类线程同时运行。

  2.4内核消除了个数上的限制,并且允许在系统运行中动态的调整进程数的上限,当时采用的是Linux Thread 线程库,它对应的线程模型是“一对一”,而线程的管理是在内核为的函数库中实现,这种线程得到了广泛的应用。但是它不与POSIX兼容。另外还有许多诸如 信号处理,进程ID等方面的问题没有完全解决。

  相似新的2.6内核中,进程调度通过重新的编写,删除了以前版本中的效率不高的算法,内核框架页也被重新编写。开始使用NPTL(Native POSIX Thread Library)线程库,这个线程库有以下几个目标: POSIX兼容,都处理结果和应用,底启动开销,低链接开销,与Linux Thread应用的二进制兼容,软硬件的可扩展能力,与C++集 成等。 这一切是2.6的内核多线程机制更加完备。

  2. Linux 线程的实现

  Linux线程的基本操作

  这里主要讲的线程以及相关操作都是用户空间的线程操作,在Linux中,一般pthread线程库是一套通用的线程库,是由POSIX提出的, 因此具有很好的可移植性。

  2.1 线程的创建: 创建线程通常使用的函数是pthread_create.

  2.2 线程的退出:

  1) 在线程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了。这是线程退出的一种方法: 运行完毕,自动退出;

  2) 调用pthread_exit函数主动退出;

  3) 进程终止函数exit函数,一旦结束了进程,那么此进程中所有线程都将无条件终止。

  一个注意点:在默认线程属性下,如果一个进程有很多线程在同时运行,一个线程在退出以后,当前线程所占用的资源并不会随着线程的终止而得到释 放。因为所有处在一个进程中的线程共享资源。

  线程中还有一个常用函数:pthread_join函数可以用于将当前线程挂起,等待其他线程结束。实际上,这个函数是就是一个线程阻塞函数, 调用它的函数将一直等待到被等待的线程结束为止。当函数返回时,被等待线程的资源就被回收。


pthread_create 函数


pthread_exit 函数


pthread_join 函数

  取消一个线程

  有时候,我们想让一个线程 能够请求另外一个线程结束,就像给它发送一个信号似的。用线程程是可以完成这一操作的,而与单处理经,线程在被要求结束执行的时候还有一种改变其行为的办 法。

  我们来看看要求一个线程结束执行的函数

http://Linux./UploadFiles_7565/201011/20101112103753362.jpg

  这个定义很明白,给定一个线程标识符,我们就能要求取消它。但在取消线形程请求的接收端,事情会稍微复杂一些,好在也不是太复杂。线形程可以用 pthread_setcancelstate设置自己的取消状态,下面是这个函数的定义:

http://Linux./UploadFiles_7565/201011/20101112103754713.jpg

如果取消请求被接受了,线程会进入第二个控制层次----用pthread_setcanceltype设置取消类型。

  稍微注意一点就是在android-ndk-r3 里是不支持int pthread_cancel(pthread_t thread); 所以想强制退出线程似乎没有更好的办法。

=================================================================================

  linux多线程pthread的函数声明在中,因此在使用该函数时,需要把该头文件引入。

  线程的创建

  1、创建

  int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(* func) (void *), void *restrict arg );

  attr: 线程属性包括:优先级、初始栈大小,是否应该成为一个守护线程。

  缺省设置,NULL

  tidp是要创建的线程,创建成功后tipd为先线程的id

  void *(* func) (void *)是一个函数指针,该函数指针的类型为void* (*)(void *)

  是一个参数为void *,返回值也为void *的函数类型。它的一个简单的例子如下

  void *thread_handler(void *arg)

  {

  return NULL;

  }

  void *restrict arg

  中的arg是void *(* func) (void *)函数指针的参数。

  补充:函数声明中多次出现了restrict,其实这是用于CPU对函数的优化使用的,restrict的使用,由程序员保证使用 restrict标志的参数间不会有内存重叠。

  获取线程自身的id

  pthread_t pthread_self(void);

  等待给定线程终止

  int pthread_join( pthread_t tid, void **status);

  statues返回等待线程的返回值

  单个线程有三种退出方式

  1.线程从启动例程中返回(return方式),返回值是现成的退出码

  2.线程被同一进程内的其他线程取消

  3.线程调用pthread_exit退出。void pthread_exit(void *rval_ptr)

  线程清理处理程序

  void pthread_clean_push(void (*rtn)(void *),void *arg)

  void pthread_clean_pop(iny excute)

  清理函数rtn的调用顺序是由pthread_clean_push函数安排的。

  它在下列几种情况下执行:

  1.调用pthread_exit时

  2.响应取消请求时

  3.用非零execute参数调用pthread_clean_pop时

  如果execute参数为0,清理函数将不被调用。无论何种情况,pthread_clean_pop都将删除上次 pthread_clean_push建立的清理处理程序。

  如果线程使用return从例程返回,那么pthread_clean_push建立的清理处理程序不会被执行。

  linux thread与fork的对比

http://Linux./UploadFiles_7565/201011/20101112103757269.jpg


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多