在上面的程序当中我们使用 mmap 系统调用在共享库空间申请了一段内存空间,并且将其做为栈空间,我们在这里就不将程序执行的结果放出来了,上面整个程序和前面的程序相差不大,只是在申请内存方面发生了变化,总体的方向是不变的 。
根据前面知识的学习,我们可以知道多个线程可以共享同一个进程虚拟地址空间,我们只需要给每个线程申请一个栈空间让线程执行起来就行,基于此我们可以知道多个线程的执行流和大致的内存布局如下图所示:

文章插图
在上图当中不同的线程拥有不同的栈空间和每个线程自己的寄存器现场,正如上图所示,栈空间可以是在堆区也可以是在共享库的映射区域,只需要给线程提供栈空间即可 。
深入理解线程的状态在
pthread
当中给我们提供了一个函数 pthread_cancel
可以取消一个正在执行的线程,取消正在执行的线程之后会将线程的退出状态(返回值)设置成宏定义 PTHREAD_CANCELED
。我们使用下面的例子去理解一下线程取消的过程:#include <stdio.h>#include <pthread.h>#include <assert.h>void* task(void* arg) { while(1) {pthread_testcancel(); // 测试是否被取消执行了}return NULL;}int main() {void* res;pthread_t t;pthread_create(&t, NULL, task, NULL);int s = pthread_cancel(t); // 取消函数的执行if(s != 0)fprintf(stderr, "cancel failed\n");pthread_join(t, &res);assert(res == PTHREAD_CANCELED);return 0;}
在上面的程序当中我们在主线程当中使用函数 pthread_cancel
函数取消线程的执行,编译执行上面的程序是可以通过的,也就是说程序正确执行了,而且 assert 也通过了 。我们先不仔细去分析上面的代码的执行流和函数的意义 。我们先需要了解一个线程的基本特性 。与线程取消执行相关的一共有两个属性,分别是:
- 取消执行的状态,线程的取消执行的状态一共有两个:
- PTHREAD_CANCEL_ENABLE:这个状态表示这个线程是可以取消的,也是线程创建时候的默认状态 。
- PTHREAD_CANCEL_DISABLE:这个状态表示线程是不能够取消的,如果有一个线程发送了一个取消请求,那么这个发送取消消息的线程将会被阻塞直到线程的取消状态变成 PTHREAD_CANCEL_ENABLE。
- 取消执行的类型,取消线程执行的类型也有两种:
- PTHREAD_CANCEL_DEFERRED:当一个线程的取消状态是这个的时候,线程的取消就会被延迟执行,知道线程调用一个是取消点的(cancellation point)函数,比如 sleep 和 pthread_testcancel ,所有的线程的默认取消执行的类型就是这个类型 。
- PTHREAD_CANCEL_ASYNCHRONOUS:如果线程使用的是这个取消类型那么线程可以在任何时候被取消执行,当他接收到了一个取消信号的时候,马上就会被取消执行,事实上这个信号的实现是使用 tgkill 这个系统调用实现的 。
有了以上的知识基础我们现在可以来谈一谈前面的两个函数了:
- pthread_cancel(t) :是给线程 t 发送一个取消请求 。
- pthread_testcancel():这个函数是一个取消点,当执行这个函数的时候,程序就会取消执行 。
经验总结扩展阅读
- 2023年1月29日艾灸吉日一览表 2023年1月29日适合艾灸吗
- 2023年9月17日上学吉日一览表 2023年9月17日是上学吉日吗
- 2023年1月29日洗澡好吗 2023年1月29日洗澡吉日一览表
- 2023年1月29日剪头发行吗 2023年1月29日剪头发吉日一览表
- 2023年1月29日分居行吗 2023年1月29日分居好不好
- 2023年9月17日训马吉日一览表 2023年9月17日适合训马吗
- 2023年9月17日搭窝吉日一览表 2023年农历八月初三宜搭窝吗
- 2023年9月17日制作猫窝黄道吉日 2023年9月17日制作猫窝吉日一览表
- 2023年1月29日给佛像开光吉日一览表 2023年1月29日给佛像开光行吗
- 2023年1月29日玉石开光好吗 2023年1月29日玉石开光吉日一览表