POSIX thread
linux pthread_create 参数

linux pthread_create 参数Linux线程的创建是一个非常重要的话题,因为线程是一个应用程序中最基本的实体之一。
Linux中的线程是使用POSIX线程库(Pthread)实现的。
该库使得在Linux系统中使用线程非常方便。
本文将介绍Pthread库中的pthead_create()函数及其参数。
pthread_create() 函数原型:``` int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void*(*start_routine) (void *), void *arg); ```pthread_create 函数接受四个参数1.参数(thread): 指向pthread_t类型的指针,用来保存线程ID。
2.参数(attr): 指向 pthread_attr_t 类型的指针,用于设置线程的属性。
通常设置为NULL,使用默认属性。
3.参数(start_routine): 线程函数指针,该函数必须接受一个(void *)类型的参数,并返回一个(void *)类型的指针。
4.参数(arg): 传递给线程函数(start_routine)的参数。
线程创建完成后,它会执行调用 pthread_create() 函数的进程中的start_routine()函数,并将传递给pthread_create() 函数的参数(arg)传递给start_routine()函数。
以下是本函数传入的参数的详细说明。
1.参数(thread)参数thread是一个指针类型的变量,用来保存线程的ID。
在进程中创建一个线程时,线程的ID将存储在此指针中。
这个参数是必需的。
2.参数(attr)参数attr是一个指向pthread_attr_t类型结构体的指针。
pthread_attr_t是Linux系统中线程的属性类型,这个结构体包含了很多控制线程性质的变量,比如优先级,调度策略等等。
操作系统实验报告1 linux初步认知和生产者消费者问题

hierarchy
CLONE_SIGHAND 子进程与父进程共享相同的信号处理(signal handler)表
CLONE_PTRACE 若父进程被 trace,子进程也被 trace
CLONE_VFORK 父进程被挂起,直至子进程释放虚拟内存资源
CLONE_VM
子进程与父进程运行于相同的内存空间
CLONE_PID
#define inc(k) if(k < BUFFER_SIZE) k = k+1;else k=0//实现对缓冲区操作的
自增函数
并定义了如下实现问题的函数模块:
int insert_item(buffer_item item)
//将生产的产品放入缓冲区
int remove_item(buffer_item *item) //从缓冲区内移走一个产品
子进程在创建时 PID 与父进程一致
CLONE_THREAD 子进程与父进程共享相同的线程群
具体的实例如下图所示:
<4>生产者消费者问题的实现: 信号量 mutex 提供对缓冲池访问的互斥要求并初始化为 1,信号量 empty 和 full 分别用
来表示空缓冲项和满缓冲项的个数,信号量 empty 初始化为 n,信号量 full 初始化为 0。
进程是父进程的复制品且子进程装入另一个新程序;在第四章的结尾介绍了 clone()创建 线程的功能,linux 并不区分进程还是线程,clone()被调用时,它被传递一组标记以决定 父任务与子任务之间发生多少共享任务的数据结构,继而又从网上了解了其他的一些方 面区别,并进行了实验 <4>有限缓冲问题是一个经典的同步问题,可以通过信号量来实现进程同步。其中信号量 mutex 提供对缓冲池访问的互斥要求并初始化为 1,信号量 empty 和 full 分别用来表示空缓 冲项和满缓冲项的个数,信号量 empty 初始化为 n,信号量 full 初始化为 0
posix接口实现方法

posix接口实现方法以POSIX接口实现方法为标题的文章POSIX(Portable Operating System Interface)是一种操作系统接口标准,旨在提供可移植性和互操作性。
POSIX接口定义了一组函数、命令和工具,用于应用程序与操作系统进行通信和交互。
本文将介绍一些常见的POSIX接口实现方法,并探讨它们在不同情况下的应用。
一、文件和目录操作接口1. 创建文件:使用open函数创建一个新文件,可以指定文件的权限和打开模式。
如果文件已存在,则会打开该文件;如果文件不存在,则会创建一个新文件。
2. 读取文件内容:使用read函数从文件中读取数据。
该函数要求提供文件描述符、缓冲区和读取的字节数,返回实际读取的字节数。
3. 写入文件内容:使用write函数将数据写入文件。
该函数要求提供文件描述符、缓冲区和写入的字节数,返回实际写入的字节数。
4. 关闭文件:使用close函数关闭文件,释放文件描述符。
5. 创建目录:使用mkdir函数创建一个新目录。
可以指定目录的权限和路径。
6. 删除目录:使用rmdir函数删除一个空目录。
7. 遍历目录:使用opendir函数打开一个目录,使用readdir函数读取目录中的文件和子目录。
二、进程管理接口1. 创建进程:使用fork函数创建一个新进程,该进程是调用进程的副本。
父进程与子进程共享代码段,但拥有独立的数据段和堆栈。
2. 等待进程结束:使用wait函数等待子进程结束,并获取子进程的返回状态。
3. 进程替换:使用exec函数族中的execve函数将当前进程替换为新的可执行文件。
该函数要求提供新程序的路径和参数。
4. 进程退出:使用exit函数终止当前进程,并返回一个退出状态。
5. 进程间通信:使用管道、共享内存、信号量等机制实现进程间的通信和同步。
三、线程管理接口1. 创建线程:使用pthread_create函数创建一个新线程。
该函数要求提供线程属性、线程入口函数和参数。
c语言创建线程的方法

c语言创建线程的方法在C语言中,可以使用标准库中的`pthread`(POSIX Threads)来创建和管理线程。
以下是使用`pthread`库创建线程的基本步骤:1. 包含头文件:在程序中包含`pthread.h`头文件。
```c#include <pthread.h>```2. 定义线程函数:创建一个函数,该函数将作为新线程的入口点。
该函数的原型应为`void *function(void *arg)`,其中`arg`是传递给线程的参数,可以为NULL。
```cvoid *myThreadFunction(void *arg) {// 线程的具体执行逻辑// ...return NULL;}```3. 声明线程变量:声明一个`pthread_t`类型的变量,用于存储新线程的标识符。
```cpthread_t myThread;```4. 创建线程:使用`pthread_create`函数创建新线程。
```cint pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void *), void *arg);```- `thread`: 用于存储新线程标识符的变量的地址。
- `attr`: 线程的属性,通常使用`NULL`表示默认属性。
- `start_routine`: 新线程的入口函数。
- `arg`: 传递给线程函数的参数。
```cint result = pthread_create(&myThread, NULL, myThreadFunction, NULL);if (result != 0) {perror("Thread creation failed");// 处理线程创建失败的情况}```5. 等待线程结束(可选):使用`pthread_join`函数等待线程的结束。
Linux系统线程创建及同步互斥方法简要说明(供查考)

Linux系统线程创建及同步互斥方法简要说明(供查考)1、.POSIX线程函数的定义在头文件pthread.h中,所有的多线程程序都必须通过使用#include<pthread.h>包含这个头文件2、用gcc编译多线程程序时,必须与pthread函数库连接。
可以使用以下两种方式编译(建议使用第一种)(1)gcc –D_REENTRANT -o 编译后的目标文件名源文件名-lpthread例如:gcc –D_REENTRANT -o pthread_create pthread_create.c -lpthread (执行该编译结果的方式为:./pthread_create)(2)gcc -pthread -o 编译后的文件名源文件名例如:gcc -pthread -o example example.c一、需要用到的函数的用法提示1、创建线程函数pthread_t a_thread; /*声明a_thread变量,用来存放创建的新线程的线程ID(线程标识符)*/int res=pthread_create(&a_thread,NULL,thread_function,NULL);/*创建一个执行函数thread_function的新线程,线程ID存放在变量a_thread */ 2、退出线程函数pthread_exit(NULL);/*那个线程在执行中调用了该方法,那个线程就退出*/创建和退出线程实例3、连接(等待)线程函数int error;int *exitcodeppthread_t tid; /*用来表示一个已经存在的线程*/error=pthread_join(tid,&exitcodep); /*执行该方法的线程将要一直等待,直到tid 表示的线程执行结束,exitcodep 存放线程tid退出时的返回值*/4、返回线程ID的函数pthread_t t/*声明表示线程的变量t */t=pthread_self( ) /*返回调用该方法的线程的线程ID*/5、判断两个线程是否相等的函数(pthread_equal)int pthread_equal(pthread_t t1, pthread_t t2);/*判断线程t1与线程t2是否线程ID相等*/二、线程同步1、使用互斥量同步线程(实现互斥)(1)互斥量的创建和初始化pthread_mutex_t a_mutex=PTHREAD_MUTEX_INITIALIZER/*声明a_mutex为互斥量,并且初始化为PTHREAD_MUTEX_INITIALIZER */ (2)锁定和解除锁定互斥量pthread_mutex_t a_mutex=PTHREAD_MUTEX_INITIALIZER/*声明互斥量a_mutex*/int rc=pthread_mutex_lock(&a_mutex) /*锁定互斥量a_mutex*/ ………………………………/*锁定后的操作*/int rd= pthread_mutex_unlock(&a_mutex) /*解除对互斥量a_mutex的锁定*/例子:利用互斥量来保护一个临界区pthread_mutex_t a_mutex=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock(&a_mutex) /*锁定互斥量a_mutex*//*临界区资源*/pthread_mutex_unlock(&a_mutex) /*解除互斥量a_mutex的锁定*/(3)销毁互斥量Int rc=pthread_mutex_destory(&a_mutex) /*销毁互斥量a_mutex*/2、用条件变量同步线程(实现真正的同步)条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。
POSIX线程程序设计(中文版)

POSIX 多线程程序设计Blaise Barney, Lawrence Livermore National Laboratory目录表1.摘要2.Pthreads 概述1.什么是线程?2.什么是Pthreads?3.为什么使用Pthreads?4.使用线程设计程序3.Pthreads API编译多线程程序4.线程管理1.创建和终止线程2.向线程传递参数3.连接(Joining)和分离(Detaching)线程4.栈管理5.其它函数5.互斥量(Mutex Variables)1.互斥量概述2.创建和销毁互斥量3.锁定(Locking)和解锁(Unlocking)互斥量6.条件变量(Condition Variable)1.条件变量概述2.创建和销毁条件变量3.等待(Waiting)和发送信号(Signaling)7.没有覆盖的主题8.Pthread 库API参考9.参考资料在多处理器共享内存的架构中(如:对称多处理系统SMP),线程可以用于实现程序的并行性。
历史上硬件销售商实现了各种私有版本的多线程库,使得软件开发者不得不关心它的移植性。
对于UNIX系统,IEEE POSIX 1003.1标准定义了一个C语言多线程编程接口。
依附于该标准的实现被称为POSIX theads 或Pthreads。
该教程介绍了Pthreads的概念、动机和设计思想。
内容包含了Pthreads API主要的三大类函数:线程管理(Thread Managment)、互斥量(Mutex Variables)和条件变量(Condition Variables)。
向刚开始学习Pthreads的程序员提供了演示例程。
适于:刚开始学习使用线程实现并行程序设计;对于C并行程序设计有基本了解。
不熟悉并行程序设计的可以参考EC3500: Introduction To Parallel Computing。
什么是线程?•技术上,线程可以定义为:可以被操作系统调度的独立的指令流。
posix接口标准

posix接口标准POSIX接口标准简介POSIX(可移植操作系统接口)是一组定义了操作系统接口的标准。
它的目的是为了实现操作系统的可移植性,使得开发者可以在不同的操作系统上编写可移植的软件。
POSIX定义了许多功能、命令以及系统调用,以便于开发者编写可移植的软件,并且保持对不同系统的一致性。
POSIX标准的内容POSIX接口标准包含了许多不同的组件,以下是其中几个重要的组件:1. 文件和目录操作:POSIX定义了一系列函数,使得开发者可以对文件和目录进行读、写、创建等操作。
例如,开发者可以使用open()函数打开一个文件,并使用read()和write()函数进行数据的读取和写入。
此外,POSIX还定义了一些标准的文件和目录路径,以及文件权限的控制。
2. 进程控制:POSIX提供了一套用于进程控制的函数。
开发者可以使用fork()函数创建一个新的进程,使用exec()函数来加载新程序并替换当前进程的地址空间,以及使用wait()函数等待一个子进程的结束。
这些函数使得进程的创建、管理和通信变得更加容易。
3. 线程控制:POSIX对线程控制也进行了定义。
通过使用线程,可以实现并发执行的能力,从而提高程序的性能。
POSIX定义了线程的创建、同步和销毁等操作。
开发者可以使用pthread_create()函数创建线程,使用mutex和condition variable等机制进行线程同步。
4. 信号处理:POSIX提供了一套用于处理信号的函数,使得开发者可以对软件中出现的不同事件做出响应。
开发者可以使用signal()函数来定义信号的处理程序,以及使用sigprocmask()来管理进程的信号屏蔽集。
5. 文件I/O:POSIX定义了标准的文件I/O接口和相关函数。
开发者可以使用fopen()和fclose()函数打开和关闭文件,使用fgets()和fputs()函数进行文件的读写操作,以及使用fseek()和ftell()函数进行文件指针的定位和查询。
pthread_tryjoin_np用法

pthread_tryjoin_np用法一、概述pthread_tryjoin_np是POSIX线程(pthread)库中的一个函数,用于尝试获取线程的退出状态,而无需等待该线程终止。
这对于某些情况下需要检查线程是否已经结束,但又不希望阻塞当前线程的执行很有用。
二、函数原型intpthread_tryjoin_np(pthread_tthread,void**ptr);三、参数说明*`thread`:要尝试获取退出的线程的标识符。
*`ptr`:一个指向要传递给线程的内存地址的指针,该地址在成功获取线程退出状态后将被返回。
如果此参数为NULL,则不会返回任何值。
四、函数返回值如果成功获取了线程的退出状态并返回目标内存地址,则函数返回0。
如果线程仍在运行,则返回一个非零值,表示操作失败。
五、注意事项*pthread_tryjoin_np与pthread_join的区别在于,前者只是尝试获取线程的退出状态,而不会等待线程终止。
因此,它不会阻塞当前线程的执行。
*如果线程已经退出,但仍然有多个线程试图获取其退出状态,则可能会发生竞态条件,这取决于系统如何处理这些尝试。
在这种情况下,应该使用其他机制来同步对线程状态的访问。
*传递给线程的内存地址必须在调用pthread_tryjoin_np之前分配,并且必须足够大以容纳返回的值。
六、示例代码下面是一个简单的示例代码,展示了如何使用pthread_tryjoin_np函数:```c#include<pthread.h>#include<stdio.h>#include<stdlib.h>intmain(){pthread_tthread;int*value;intresult;//创建并启动线程result=pthread_create(&thread,NULL,&thread_function,NULL);if(result!=0){perror("Threadcreationfailed");exit(EXIT_FAILURE);}//尝试获取线程退出状态并打印结果值value=malloc(sizeof(int));//分配内存地址result=pthread_tryjoin_np(thread,value);if(result==0){printf("Threadexitedwithvalue:%d\n",*value);}else{printf("Threadisstillrunning\n");}//等待线程结束(可选)pthread_join(thread,NULL);//不阻塞当前线程的执行free(value);//释放内存地址return0;}```上述代码中,首先创建并启动一个线程,然后尝试使用pthread_tryjoin_np 函数获取该线程的退出状态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
POSIX 线程详解 1POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段。
在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程。
其中还涉及大量幕后细节,读完本系列文章,您完全可以运用POSIX 线程创建多线程程序。
线程是有趣的了解如何正确运用线程是每一个优秀程序员必备的素质。
线程类似于进程。
如同进程,线程由内核按时间分片进行管理。
在单处理器系统中,内核使用时间分片来模拟线程的并发执行,这种方式和进程的相同。
而在多处理器系统中,如同多个进程,线程实际上一样可以并发执行。
那么为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间。
不同的线程可以存取内存中的同一个变量。
所以,程序中的所有线程都可以读或写声明过的全局变量。
如果曾用 fork() 编写过重要代码,就会认识到这个工具的重要性。
为什么呢?虽然 fork() 允许创建多个进程,但它还会带来以下通信问题: 如何让多个进程相互通信,这里每个进程都有各自独立的内存空间。
对这个问题没有一个简单的答案。
虽然有许多不同种类的本地 IPC (进程间通信),但它们都遇到两个重要障碍:强加了某种形式的额外内核开销,从而降低性能。
对于大多数情形,IPC 不是对于代码的“自然”扩展。
通常极大地增加了程序的复杂性。
双重坏事: 开销和复杂性都非好事。
如果曾经为了支持 IPC 而对程序大动干戈过,那么您就会真正欣赏线程提供的简单共享内存机制。
由于所有的线程都驻留在同一内存空间,POSIX 线程无需进行开销大而复杂的长距离调用。
只要利用简单的同步机制,程序中所有的线程都可以读取和修改已有的数据结构。
而无需将数据经由文件描述符转储或挤入紧窄的共享内存空间。
仅此一个原因,就足以让您考虑应该采用单进程/多线程模式而非多进程/单线程模式。
线程是快捷的不仅如此。
线程同样还是非常快捷的。
与标准 fork() 相比,线程带来的开销很小。
内核无需单独复制进程的内存空间或文件描述符等等。
这就节省了大量的 CPU 时间,使得线程创建比新进程创建快上十到一百倍。
因为这一点,可以大量使用线程而无需太过于担心带来的 CPU 或内存不足。
使用 fork() 时导致的大量 CPU 占用也不复存在。
这表示只要在程序中有意义,通常就可以创建线程。
当然,和进程一样,线程将利用多 CPU。
如果软件是针对多处理器系统设计的,这就真的是一大特性(如果软件是开放源码,则最终可能在不少平台上运行)。
特定类型线程程序(尤其是 CPU 密集型程序)的性能将随系统中处理器的数目几乎线性地提高。
如果正在编写 CPU 非常密集型的程序,则绝对想设法在代码中使用多线程。
一旦掌握了线程编码,无需使用繁琐的 IPC 和其它复杂的通信机制,就能够以全新和创造性的方法解决编码难题。
所有这些特性配合在一起使得多线程编程更有趣、快速和灵活。
线程是可移植的如果熟悉 Linux 编程,就有可能知道 __clone() 系统调用。
__clone() 类似于 fork(),同时也有许多线程的特性。
例如,使用 __clone(),新的子进程可以有选择地共享父进程的执行环境(内存空间,文件描述符等)。
这是好的一面。
但 __clone() 也有不足之处。
正如__clone() 在线帮助指出:“__clone 调用是特定于 Linux 平台的,不适用于实现可移植的程序。
欲编写线程化应用程序(多线程控制同一内存空间),最好使用实现 POSIX 1003.1c 线程 API 的库,例如 Linux-Threads 库。
参阅pthread_create(3thr)。
”虽然 __clone() 有线程的许多特性,但它是不可移植的。
当然这并不意味着代码中不能使用它。
但在软件中考虑使用 __clone() 时应当权衡这一事实。
值得庆幸的是,正如 __clone() 在线帮助指出,有一种更好的替代方案:POSIX 线程。
如果想编写可移植的多线程代码,代码可运行于 Solaris、FreeBSD、Linux 和其它平台,POSIX 线程是一种当然之选。
第一个线程下面是一个 POSIX 线程的简单示例程序:thread1.c#include#include#includevoid *thread_function(void *arg) {int i;for ( i=0; i<20; i++) {printf("Thread says hi!n");sleep(1);}return NULL;}int main(void) {pthread_t mythread;if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {printf("error creating thread.");abort();}if ( pthread_join ( mythread, NULL ) ) {printf("error joining thread.");abort();}exit(0);}要编译这个程序,只需先将程序存为 thread1.c,然后输入:$ gcc thread1.c -o thread1 -lpthread运行则输入:$ ./thread1理解 thread1.cthread1.c 是一个非常简单的线程程序。
虽然它没有实现什么有用的功能,但可以帮助理解线程的运行机制。
下面,我们一步一步地了解这个程序是干什么的。
main() 中声明了变量 mythread,类型是 pthread_t。
pthread_t 类型在 pthread.h 中定义,通常称为“线程 id”(缩写为 "tid")。
可以认为它是一种线程句柄。
mythread 声明后(记住 mythread 只是一个 "tid",或是将要创建的线程的句柄),调用 pthread_create函数创建一个真实活动的线程。
不要因为 pthread_create() 在 "if" 语句内而受其迷惑。
由于pthread_create() 执行成功时返回零而失败时则返回非零值,将 pthread_create() 函数调用放在 if() 语句中只是为了方便地检测失败的调用。
让我们查看一下 pthread_create 参数。
第一个参数 &mythread 是指向 mythread 的指针。
第二个参数当前为 NULL,可用来定义线程的某些属性。
由于缺省的线程属性是适用的,只需将该参数设为 NULL。
第三个参数是新线程启动时调用的函数名。
本例中,函数名为 thread_function()。
当 thread_function() 返回时,新线程将终止。
本例中,线程函数没有实现大的功能。
它仅将 "Thread says hi!" 输出 20 次然后退出。
注意 thread_function() 接受 void * 作为参数,同时返回值的类型也是 void *。
这表明可以用 void * 向新线程传递任意类型的数据,新线程完成时也可返回任意类型的数据。
那如何向线程传递一个任意参数?很简单。
只要利用 pthread_create() 中的第四个参数。
本例中,因为没有必要将任何数据传给微不足道的 thread_function(),所以将第四个参数设为 NULL。
您也许已推测到,在 pthread_create() 成功返回之后,程序将包含两个线程。
等一等,两个线程?我们不是只创建了一个线程吗?不错,我们只创建了一个进程。
但是主程序同样也是一个线程。
可以这样理解:如果编写的程序根本没有使用 POSIX 线程,则该程序是单线程的(这个单线程称为“主”线程)。
创建一个新线程之后程序总共就有两个线程了。
我想此时您至少有两个重要问题。
第一个问题,新线程创建之后主线程如何运行。
答案,主线程按顺序继续执行下一行程序(本例中执行 "if (pthread_join(...))")。
第二个问题,新线程结束时如何处理。
答案,新线程先停止,然后作为其清理过程的一部分,等待与另一个线程合并或“连接”。
现在,来看一下 pthread_join()。
正如 pthread_create() 将一个线程拆分为两个, pthread_join() 将两个线程合并为一个线程。
pthread_join() 的第一个参数是 tid mythread。
第二个参数是指向 void 指针的指针。
如果 void 指针不为 NULL,pthread_join 将线程的 void * 返回值放置在指定的位置上。
由于我们不必理会 thread_function() 的返回值,所以将其设为 NULL.您会注意到 thread_function() 花了 20 秒才完成。
在 thread_function() 结束很久之前,主线程就已经调用了 pthread_join()。
如果发生这种情况,主线程将中断(转向睡眠)然后等待 thread_function() 完成。
当 thread_function() 完成后, pthread_join() 将返回。
这时程序又只有一个主线程。
当程序退出时,所有新线程已经使用 pthread_join() 合并了。
这就是应该如何处理在程序中创建的每个新线程的过程。
如果没有合并一个新线程,则它仍然对系统的最大线程数限制不利。
这意味着如果未对线程做正确的清理,最终会导致 pthread_create() 调用失败。
无父,无子如果使用过 fork() 系统调用,可能熟悉父进程和子进程的概念。
当用 fork() 创建另一个新进程时,新进程是子进程,原始进程是父进程。
这创建了可能非常有用的层次关系,尤其是等待子进程终止时。
例如,waitpid() 函数让当前进程等待所有子进程终止。
waitpid() 用来在父进程中实现简单的清理过程。
而 POSIX 线程就更有意思。
您可能已经注意到我一直有意避免使用“父线程”和“子线程”的说法。
这是因为 POSIX 线程中不存在这种层次关系。
虽然主线程可以创建一个新线程,新线程可以创建另一个新线程,POSIX 线程标准将它们视为等同的层次。
所以等待子线程退出的概念在这里没有意义。
POSIX 线程标准不记录任何“家族”信息。
缺少家族信息有一个主要含意:如果要等待一个线程终止,就必须将线程的 tid 传递给 pthread_join()。
线程库无法为您断定 tid。