在上面的程序当中我们使用一个参数 ret 去获取线程的退出码 , 从上面的结果我们可以知道 , 我们得到了正确的结果 。
如果我们没有在线程执行的函数当中使用 pthread_exit 函数当中明确的指出线程的退出码 , 线程的退出码就是函数的返回值 。比如下面的的程序:
#include <stdio.h>#include <pthread.h>#include <sys/types.h>void* func(void* arg){ return (void*)100;}int main() { pthread_t t; pthread_create(&t, NULL, func, NULL); void* ret; pthread_join(t, &ret); printf("ret = %ld\n", (u_int64_t)(ret)); return 0;}上面的程序的输出结果也是 100 , 这与我们期待的结果是一致的 。
获取线程的栈帧和PC值在多线程的程序当中 , 每个线程拥有自己的栈帧和PC寄存器(执行的代码的位置 , 在 x86_86 里面就是 rip 寄存器的值) 。在下面的程序当中我们可以得到程序在执行时候的三个寄存器 rsp, rbp, rip 的值 , 我们可以看到 , 两个线程执行时候的输出是不一致的 , 这个也从侧面反映出来线程是拥有自己的栈帧和PC值的 。
#include <stdio.h>#include <pthread.h>#include <sys/types.h>u_int64_t rsp;u_int64_t rbp;u_int64_t rip;void find_rip() { asm volatile( "movq 8(%%rbp), %0;" :"=r"(rip):: );}void* func(void* arg) { printf("In func\n"); asm volatile( \ "movq %%rsp, %0;" \ "movq %%rbp, %1;" \ :"=m"(rsp), "=m"(rbp):: \ ); find_rip(); printf("stack frame: rsp = %p rbp = %p rip = %p\n", (void*)rsp, (void*)rbp, (void*) rip); return NULL;}int main() { printf("================\n"); printf("In main\n"); asm volatile( \ "movq %%rsp, %0;" \ "movq %%rbp, %1;" \ :"=m"(rsp), "=m"(rbp):: \ ); find_rip(); printf("stack frame: rsp = %p rbp = %p rip = %p\n", (void*)rsp, (void*)rbp, (void*) rip); printf("================\n"); pthread_t t; pthread_create(&t, NULL, func, NULL); pthread_join(t, NULL); return 0;}上面的程序的输出结果如下所示:
================In mainstack frame: rsp = 0x7ffc47096d50 rbp = 0x7ffc47096d80 rip = 0x4006c6================In funcstack frame: rsp = 0x7f0a60d43ee0 rbp = 0x7f0a60d43ef0 rip = 0x400634从上面的结果来看主线程和线程 t 执行的是不同的函数 , 而且两个函数的栈帧差距还是很大的 , 我们计算一下 0x7ffc47096d80 - 0x7f0a60d43ef0 = 1038949363344 = 968G 的内存 , 因此很明显这两个线程使用的是不同的栈帧 。
经验总结扩展阅读
- 十二星座是怎样解读爱情的
- 如何理解Java中眼花缭乱的各种并发锁?
- 十二星座中不适合异地恋的星座
- 2023年农历二月二十九出生的男孩命运和五行分析
- 2023年阴历五月初二日是封顶的好日子吗
- 2023年7月29日农历六月十二是乔迁最佳日期吗 2023年7月29日适不适合乔迁
- 2023年农历九月二十六能不能搬家入伙 农历二零二三年九月廿六能不能搬家
- 2023年农历九月二十七吉利吗 今天宜搬入新家吗
- 2023年农历九月二十八可以搬家吗 2023年农历九月二十八搬家怎么样
- 二宁是哪两个省