linux线程的创建与删除

使用linux线程时,编译时需要包含-pthread选项。

Linux通用API返回0表示成功,返回-1表示失败,并设置errno以标识错误原因。但Pthreads相关的API却与之不同,返回0 表示成功,返回正值表示失败,正值的含义与errno相同。

我们可以使用pthread_create()来创建线程。创建成功后的线程可以使用如下几种方式终止:

  1. 线程主函数中执行return语句并返回指定值。
  2. 调用pthread_exit()函数终止线程
  3. 调用pthread_cancel()取消线程。
  4. 任意线程调用了exit(),或者主线程执行了return语句(在main()函数中),都会导致进程中的所有线程立即终止。

当线程终止退出时,分两种情况:

  1. 线程为可连接(joinable)状态。这也是线程的默认状态。这种状态的线程退出时,必须使用pthread_join()函数连接。用于资源回收。否则会产生相当于僵尸进程的线程。除了浪费系统资源以外,僵尸线程若累积过多,应用将再也无法创建新的线程。
  2. 线程为分离(detached)状态。调用pthread_detach()将该线程标记为处于分离(detached)状态。一旦线程被分离,就不可能再使用pthread_join()来获得它的返回状态,并且该线程也不能再次连接。这种情况一般用于程序员并不关心线程的返回状态,只是希望系统在线程终止时能够自动清理并移除之。

线程使用相关的函数API:

  1. int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg)

    1. 创建一个线程
    2. thread:用于保存线程标识符的实体指针。
    3. attr:用于指定要创建线程的各种属性。
    4. start_routine:线程实体函数
    5. arg:线程实体函数的参数。
    6. return:
  2. void pthread_exit(void *retval)
    1. 终止当前线程。
    2. retval:指定线程的返回内容。pthread_join()可获取返回的内容。retval内容不能是局部变量。必须为全局变量等。
  3. pthread_t pthread_self(void)
    1. 获取当前线程的id.
  4. int pthread_equal(pthread_t t1, pthread_t t2)
    1. 检查两个线程是否相等。
    2. return:if true:返回非0值。if false:返回0.
  5. int pthread_join(pthread_t thread, void **retval)
    1. 等待某个指定的线程终止。
    2. thread:指定要等待终止的线程id.
    3. retval:用于接收线程终止后返回的内容。
    4. return:if true:0. if false:大于0的错误码。
    5. 注意:当线程终止时,必须使用pthread_join()函数连接。否则会产生相当于僵尸进程的线程。除了浪费系统资源以外,僵尸线程若累积过多,应用将再也无法创建新的线程。
    6. 注意:线程之间的关系是对等的。即没有进程中的父子关系等。因此进程中的任意线程均可以调用pthread_join()与该进程的任何其他线程连接起来。
  6. int pthread_detach(pthread_t thread)
    1. 默认情况下,线程是可连接的(joinable),也就是说,当线程退出时,其他线程可以通过调用pthread_join()获取其返回状态。有时,程序员并不关心线程的返回状态,只是希望系统在线程终止时能够自动清理并移除之。在这种情况下,可以调用pthread_detach()并向thread 参数传入指定线程的标识符,将该线程标记为处于分离(detached)状态。一旦线程被分离,就不可能再使用pthread_join()来获得它的返回状态,并且该线程也不能再次连接。
    2. thread:线程id
    3. return:if true:0. if false:大于0的错误码。

如下是一个简单的线程创建例程:

#include <pthread.h>
#include <stdio.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>void *thread_entry(void *arg)
{int num = 0;int count = *((int *)arg);for (int i = 0; i < count; i++){num ++;}return NULL;
}void main(void)
{// 1. 定义线程描述符pthread_t t1;int counts = 20000;// 2. 创建线程if(pthread_create(&t1, NULL, thread_entry, &counts) != 0){printf("thread t1 create error.");exit(1);}// 3. 回收线程资源if(pthread_join(t1, NULL) != 0){printf("pthread_join t1 error.");exit(1);}exit(0);
}

线程取消

上面提到的线程终止函数pthread_exit()用于自身线程的终止。但有时也需要其他线程来终止当前线程。这时就涉及到线程取消了。

线程取消:其他线程向本线程发送一个请求,要求本线程其立即退出。线程取消函数thread_cancel()只负责发送一个取消请求消息,然后立即返回。至于目标线程如何处理这个请求的,取决于目标线程的取消状态state和类型type

当因线程取消导致线程终止时,终止返回的内容为PTHREAD_CANCELED.即pthread_join()中第二个参数获取到的值将是一个特殊值:PTHREAD_CANCELED

  1. int pthread_cancel(pthread_t thread)

    1. 向目标线程发送取消请求。
    2. thread:目标线程id
    3. return:if true:0. if false:大于0的错误码。
  2. int pthread_setcancelstate(int state, int *oldstate)
    1. 设置当前线程的取消状态。
    2. state:要设置的状态,如下:
      1. PTHREAD_CANCEL_DISABLE:线程不可取消。如果此类线程收到取消请求,则会将请求挂起,直至将线程的取消状态置为启用。
      2. PTHREAD_CANCEL_ENABLE:线程可以取消。新建线程时的默认值。
    3. oldstate:用于返回之前的状态。
    4. return:if true:0. if false:大于0的错误码。
  3. int pthread_setcanceltype(int type, int *oldtype)
    1. 设置当前线程的取消类型。在取消状态设置为PTHREAD_CANCEL_ENABLE时使用。
    2. type:要设置的类型。
      1. PTHREAD_CANCEL_ASYNCHRONOUS:异步取消线程。即在线程的任何地方都可以取消。很少用。
      2. PTHREAD_CANCEL_DEFERED:取消请求保持挂起状态,直至到达取消点.新建线程时的默认值。
        1. 什么是取消点:简单说就是一些系统规定的可以取消线程的函数。当满足上述条件时(即state为使能,type为挂起),遇到这些函数线程就会终止。系统规定规定的取消点函数很多,如open()等各种系统调用。详见man手册。
    3. oldtype:用于返回之前的类型。
    4. return:if true:0. if false:大于0的错误码。
  4. void pthread_testcancel(void)
    1. 产生一个取消点。即如果线程中没有使用系统规定取消点函数。可以使用此函数来产生取消点,而不影响程序逻辑。

在线程取消时,可能会涉及到内存释放,互斥量恢复等操作。这时会涉及到线程清理相关的函数。

  1. void pthread_cleanup_push(void (*routine)(void*), void *arg)

    1. 将指定清理函数压栈。线程因取消请求进入终止状态时,会从栈顶向下依次运行栈中的清理函数。
    2. routine:清理函数
    3. arg:清理函数要传入的参数
  2. void pthread_cleanup_pop(int execute)
    1. 出栈。配合pthread_cleanup_push()使用。它俩必须属于同一语法块,必须一一对应。
    2. execute:执行状态。
      1. 0:正常出栈,不执行栈顶的清理函数。
      2. !0,出栈时,仍然会执行栈顶的清理函数。

关于技术交流

此处后的文字已经和题目内容无关,可以不看。
qq群:825695030
微信公众号:嵌入式的日常
如果上面的文章对你有用,欢迎打赏、点赞、评论。

linux线程的创建与删除相关推荐

  1. Linux 线程的创建与同步

    Linux 线程的创建与同步 1.线程的定义 2.线程的创建和使用 3.理解线程的并发运行 3.线程同步 3.线程的实现 1.线程的定义 线程:进程内部的一条执行路径.是资源调度和执行的基本单位. 进 ...

  2. linux命令 - ln - 创建和删除软、硬链接

    linux命令 - ln - 创建和删除软.硬链接 在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号.文件属性保存在索引结点里,在访问文件 ...

  3. 学习Linux二(创建、删除文件和文件夹命令)

    学习Linux二(创建.删除文件和文件夹命令) 今天学习了几个命令,是创建.删除文件和文件夹的,在linux里,文件夹是目录,下面说下我学习的命令. 创建文件夹[mkdir] 一.mkdir命令使用权 ...

  4. Linux 学习之创建、删除文件和文件夹命令

    今天学习了几个命令,是创建.删除文件和文件夹的,在linux里,文件夹是目录,下面说下我学习的命令. 创建文件夹[mkdir] 一.mkdir命令使用权限 所有用户都可以在终端使用 mkdir 命令在 ...

  5. 浅析Linux线程的创建

    本文首先使用了接口pthread_create创建一个线程,并用strace命令追踪了接口pthread_create创建线程的步骤以及涉及到的系统调用,然后讨论了Linux中线程与进程关系,最后概述 ...

  6. linux软链接的创建、删除和更新

    大家都知道,有的时候,我们为了省下空间,都会使用链接的方式来进行引用操作.同样的,在系统级别也有.在Windows系列中,我们称其为快捷方式,在Linux中我们称其为链接(基本上都差不多了,其中可能有 ...

  7. linux内核系统调用创建和删除文件

    一.创建文件 1.创建普通文件 int creat(const char *pathname, mode_t mode); 也可以使用open和openat创建普通文件:如果参数flags设置标志位O ...

  8. linux在个人目录下新建目录,Linux目录的创建与删除命令

    mkdir命令 功能:创建一个目录(类似MSDOS下的md命令). 语法:mkdir [选项] dir-name 说明:该命令创建由dir-name命名的目录.要求创建目录的用户在当前目录中(dir- ...

  9. Linux 学习之创建,删除文件和文件夹命令

    https://blog.csdn.net/linjpg/article/details/77854671

最新文章

  1. JavaScript 正则表达式的使用
  2. linux diff patch 生成和打补丁
  3. java求职攻略_2020年求职攻略 《Java面试连成诀》教程免费分享
  4. Java ServletContext 详解
  5. php workman 多线程,workerman如何多线程
  6. Ext grid js上移下移样例
  7. 利用微软的平台进行Office文档的在线查看
  8. 磁盘测试----fio
  9. 深度学习2.0-32.经典卷积网络VGG,GoogleNet,Inception-1
  10. java音频播放(转)
  11. 单应性(同义词直射变换、射影变换和射影性等)(来自wiki)
  12. java基本类型运算溢出_JAVACard 基本数据类型的运算及溢出问题
  13. python 读取geotiff_python gdal 写GeoTiff文件
  14. background背景图片铺满背景并且不重复
  15. 怎么使用山东鼎信发送短信验证码
  16. [转载]tensorflow二次开发
  17. 张勋说:棒磨机断棒的几个可能原因
  18. MSP430寄存器的设置与作用
  19. WOS(SCI)爬虫案例
  20. 平板win10 android哪个耗电,买平板电脑时,应该选win10还是安卓系统?

热门文章

  1. VMD安装(无root权限不联网不配置环境变量)
  2. 火鸟出击主图源码指标
  3. css第04天之浮动
  4. Python函数编程——函数简介
  5. windows用docker拉取mysql
  6. 基于Particles.js的粒子动态背景
  7. 个人微信公众号文章留言功能开通方法,无需迁移账号,三个步骤轻松完成
  8. 小技巧---火狐浏览器显示书签栏
  9. sd卡和tf卡的一些常识
  10. java.awt.GridBagConstraints