pthread
POSIX Threads简称Pthreads,Pthreads是线程的POSIX标准,该标准定义了一套C程序语言的类型、函数和常量。定义在pthread.h头文件和一个线程库里,大约有100个API,所有API都带有"pthread_"前缀,可以分为4大类:
-
线程管理(Thread
management):包括线程创建(creating)、分离(detaching)、连接(joining)及设置和查询线程属性的函数等。 -
互斥锁(Mutex):"mutual
exclusion"的缩写,用了限制线程对共享数据的访问,保护共享数据的完整性。包括创建、销毁、锁定和解锁互斥锁及一些用于设置或修改互斥量属性等函数。 -
条件变量(Condition
variable):用于共享一个互斥量的线程间的通信。包括条件变量的创建、销毁、等待和发送信号(signal)等函数。 -
读写锁(read/write lock)和屏障(barrier):包括读写锁和屏障的创建、销毁、等待及相关属性设置等函数。
-
POSIX信号量(semaphore)和Pthreads一起使用,但不是Pthreads标准定义的一部分,被定义在POSIX.1b,
Real-time extensions (IEEE Std1003.1b-1993)标准里。因此信号量相关函数的前缀是"sem"而不是"pthread"。 -
消息队列(Message queue)和信号量一样,和Pthreads一起使用,也不是Pthreads标准定义的一部分,被定义在IEEE Std1003.1-2001标准里。消息队列相关函数的前缀是"mq_"。
pthread_ 线程本身和各种相关函数
pthread_attr_ 线程属性对象
Pthread_mutex_ 互斥锁
pthread_mutexattr_ 互斥锁属性对象
pthread_cond_ 条件变量
pthread_condattr_ 条件变量属性对象
pthread_rwlock_ 读写锁
pthread_rwlockattr_ 读写锁属性对象
pthread_spin_ 自旋锁
pthread_barrier_ 屏障
pthread_barrierattr_ 屏障属性对象
sem_ 信号量
mq_ 消息队列
绝大部分Pthreads的函数执行成功则返回0值,不成功则返回一个包含在<errno.h>头文件中的错误代码。很多操作系统都支持Pthreads,比如Linux、MacOS X、 Android 和Solaris,因此使用Pthreads的函数编写的应用程序有很好的可移植性,可以在很多支持Pthreads的平台上直接编译运行。
创建线程
typedef rt_thread_t pthread_t;
pthread_t是rt_thread_t类型的重定义,定义在pthread.h头文件里。rt_thread_t是RT-Thread的线程句柄(或线程标识符),是指向线程控制块的指针。在创建线程前需要先定义一个pthread_t类型的变量。每个线程都对应了自己的线程控制块,线程控制块是操作系统用于控制线程的一个数据结构,它存放了线程的一些信息,例如优先级,线程名称和线程堆栈地址等。线程控制块及线程具体信息在RT-Thread编程手册的线程调度与管理一章有详细的介绍。
int pthread_create (pthread_t *tid,
const pthread_attr_t *attr,
void *(*start) (void *), void *arg);
参数 | 作用 |
---|---|
tid | 指向线程句柄(线程标识符)的指针,不能为NULL |
attr | 指向线程属性的指针,如果使用NULL,则使用默认的线程属性 |
start | 线程入口函数地址 |
arg | 传递给线程入口函数的参数 |
线程脱离deatch
int pthread_detach (pthread_t thread);
调用此函数,如果pthread线程没有结束,则将thread线程属性的分离状态设置为detached;当thread线程已经结束时,系统将回收pthread线程占用的资源。
线程脱离示例代码
以下程序会初始化2个线程,它们拥有相同的优先级,并按照时间片轮转调度。2个线程都会被设置为脱离状态,2个线程循环打印3次信息后自动退出,退出后系统将会自动回收其资源。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
/* 线程控制块 */
static pthread_t tid1;
static pthread_t tid2;
/* 函数返回值检查 */
static void check_result(char* str,int result)
{
if (0 == result)
{
printf("%s successfully!\n",str);
}
else
{
printf("%s failed! error code is %d\n",str,result);
}
}
/* 线程1入口函数*/
static void* thread1_entry(void* parameter)
{
int i;
printf("i'm thread1 and i will detach myself!\n");
pthread_detach(pthread_self()); /*线程1脱离自己*/
for (i = 0;i < 3;i++) /* 循环打印3次信息 */
{
printf("thread1 run count: %d\n",i);
sleep(2); /* 休眠2秒 */
}
printf("thread1 exited!\n");
return NULL;
}
/* 线程2入口函数*/
static void* thread2_entry(void* parameter)
{
int i;
for (i = 0;i < 3;i++) /* 循环打印3次信息 */
{
printf("thread2 run count: %d\n",i);
sleep(2); /* 休眠2秒 */
}
printf("thread2 exited!\n");
return NULL;
}
/* 用户应用入口 */
int rt_application_init()
{
int result;
/* 创建线程1,属性为默认值,分离状态为默认值joinable,
* 入口函数是thread1_entry,入口函数参数为NULL */
result = pthread_create(&tid1,NULL,thread1_entry,NULL);
check_result("thread1 created",result);
/* 创建线程2,属性为默认值,分离状态为默认值joinable,
* 入口函数是thread2_entry,入口函数参数为NULL */
result = pthread_create(&tid2,NULL,thread2_entry,NULL);
check_result("thread2 created",result);
pthread_detach(tid2); /* 脱离线程2 */
//while(1);
return 0;
}
线程join
int pthread_join (pthread_t thread, void **value_ptr);
以下程序代码会初始化2个线程,它们拥有相同的优先级,相同优先级的线程是按照时间片轮转调度。2个线程属性的分离状态为默认值joinable,线程1先开始运行,循环打印3次信息后结束。线程2调用pthread_join()阻塞等待线程1结束,并回收线程1占用的资源,然后线程2每隔2秒钟会打印一次信息。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
/* 线程控制块*/
static pthread_t tid1;
static pthread_t tid2;
/* 函数返回值检查 */
static void check_result(char* str,int result)
{
if (0 == result)
{
printf("%s successfully!\n",str);
}
else
{
printf("%s failed! error code is %d\n",str,result);
}
}
/* 线程1入口函数 */
static void* thread1_entry(void* parameter)
{
int i;
for (int i = 0;i < 3;i++) /* 循环打印3次信息 */
{
printf("thread1 run count: %d\n",i);
sleep(2); /* 休眠2秒 */
}
printf("thread1 exited!\n");
return NULL;
}
/* 线程2入口函数*/
static void* thread2_entry(void* parameter)
{
int count = 0;
void* thread1_return_value;
/* 阻塞等待线程1运行结束 */
pthread_join(tid1, NULL);
/* 线程2打印信息开始输出 */
while(1)
{
/* 打印线程计数值输出 */
printf("thread2 run count: %d\n",count ++);
sleep(2); /* 休眠2秒 */
}
return NULL;
}
/* 用户应用入口 */
int rt_application_init()
{
int result;
/* 创建线程1,属性为默认值,分离状态为默认值joinable,
* 入口函数是thread1_entry,入口函数参数为NULL */
result = pthread_create(&tid1,NULL,thread1_entry,NULL);
check_result("thread1 created",result);
/* 创建线程2,属性为默认值,分离状态为默认值joinable,
* 入口函数是thread2_entry,入口函数参数为NULL */
result = pthread_create(&tid2,NULL,thread2_entry,NULL);
check_result("thread2 created",result);
return 0;
}
int main()
{
rt_application_init();
while(1);
return 0;
}
线程退出exit
void pthread_exit(void *value_ptr);
这个程序会初始化2个线程,它们拥有相同的优先级,相同优先级的线程是按照时间片轮转调度。2个线程属性的分离状态为默认值joinable,线程1先开始运行,打印一次信息后休眠2秒,之后打印退出信息然后结束运行。线程2调用pthread_join()阻塞等待线程1结束,并回收线程1占用的资源,然后线程2每隔2秒钟会打印一次信息。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
/* 线程控制块 */
static pthread_t tid1;
static pthread_t tid2;
/* 函数返回值核对函数 */
static void check_result(char* str,int result)
{
if (0 == result)
{
printf("%s successfully!\n",str);
}
else
{
printf("%s failed! error code is %d\n",str,result);
}
}
/* 线程1入口函数*/
static void* thread1_entry(void* parameter)
{
int count = 0;
while(1)
{
/* 打印线程计数值输出 */
printf("thread1 run count: %d\n",count ++);
sleep(2); /* 休眠2秒 */
printf("thread1 will exit!\n");
pthread_exit(0); /* 线程1主动退出 */
}
}
/* 线程2入口函数*/
static void* thread2_entry(void* parameter)
{
int count = 0;
/* 阻塞等待线程1运行结束 */
pthread_join(tid1,NULL);
/* 线程2开始输出打印信息 */
while(1)
{
/* 打印线程计数值输出 */
printf("thread2 run count: %d\n",count ++);
sleep(2); /* 休眠2秒 */
}
}
/* 用户应用入口 */
int rt_application_init()
{
int result;
/* 创建线程1,属性为默认值,分离状态为默认值joinable,
* 入口函数是thread1_entry,入口函数参数为NULL */
result = pthread_create(&tid1,NULL,thread1_entry,NULL);
check_result("thread1 created",result);
/* 创建线程2,属性为默认值,分离状态为默认值joinable,
* 入口函数是thread2_entry,入口函数参数为NULL */
result = pthread_create(&tid2,NULL,thread2_entry,NULL);
check_result("thread2 created",result);
return 0;
}
int main()
{
rt_application_init();
while(1);
return 0;
}
以上所有资料参考自:https://www.bookstack.cn/read/rtthread-manual-doc/16.2.md