7.9. PTHREAD API
Overview
SDK中提供了两种操作系统API,一种是基于FreeRTOS原接口进行再次封装的API(这里简称为OS API), 在SDK有更好的兼容性,所以SDK中大量采用了这类API(具体请参考 OS API );另一种为POSIX Threads(这里简称为pthread api);
7.9.1. DEMO
使用工程:示例代码见 apps/common/example/system/os/pthreads_api/main.c
,测试时需要在 apps/demo/demo_DevKitBoard/include/demo_config.h
,开启宏 USE_PTHREAD_API_TEST
。
示例说明
展示了PTHREAD API基本使用方法,包括任务创建、信号量、互斥量的使用和消息队列的使用等,主要示例包括:
posix_mutex_test(); 互斥量使用示例
posix_queue_test(); 消息队列使用示例
posix_sem_test(); 信号量使用示例
7.9.2. 线程(Task)
线程创建
函数 |
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*startroutine)(void *), void *arg) |
---|---|
描述 |
创建线程 |
参数 |
thread:指向线程句柄的指针,不能为NULL attr: 指向线程属性的指针,如果使用NULL,则使用默认的线程属性 startroutine:线程入口函数地址 arg: 传递给线程入口函数的参数 |
返回值 |
0:成功 其他:失败 |
例子
#include <pthread.h> static pthread_t thread1; static pthread_t thread2; static void* thread_entry(void* parameter) { int cnt = 0; int data = (int) parameter; while (1) { printf("data : %d, cnt : %d\n", data, cnt++); sleep(5); } return NULL; } int application_init() { int ret; int data1 = 1; int data2 = 2; /** 创建线程1*/ ret = pthread_create(&thread1, NULL, thread_entry, (void*)data1); if(0 != ret) printf("pthread_create failed! error code is %d\n", ret); /** 创建线程2*/ ret = pthread_create(&thread2, NULL, thread_entry, (void*)data2); if(0 != ret) printf("pthread_create failed! error code is %d\n", ret); return 0; }
阻塞等待线程退出
函数 |
int pthread_join(pthread_t thread, void **retval); |
---|---|
描述 |
阻塞等待线程退出 |
参数 |
thread:线程句柄 retval: 用户定义的指针,用来存储被等待线程的返回值地址 |
返回值 |
0:成功 其他:失败 |
例子
#include <pthread.h> static pthread_t thread1; static pthread_t thread2; static void* thread_entry1(void* parameter) { int cnt = 0; int data = (int) parameter; for(int i; i < 4; i++) { printf("data : %d, cnt : %d\n", data, cnt++); sleep(5); } printf("thread1 exited!\n"); return NULL; } static void* thread_entry2(void* parameter) { int cnt = 0; int data = (int) parameter; /** 阻塞等待线程1运行退出 */ pthread_join(thread1, NULL); for(int i; i < 4; i++) { printf("data : %d, cnt : %d\n", data, cnt++); sleep(5); } printf("thread1 exited!\n"); return NULL; } int application_init() { int ret; int data1 = 1; int data2 = 2; /** 创建线程1*/ ret = pthread_create(&thread1, NULL, thread_entry1, (void*)data1); if(0 != ret) printf("pthread_create failed! error code is %d\n", ret); /** 创建线程2*/ ret = pthread_create(&thread2, NULL, thread_entry2, (void*)data2); if(0 != ret) printf("pthread_create failed! error code is %d\n", ret); return 0; }
退出线程
函数 |
void pthread_exit(void *value_ptr) |
---|---|
描述 |
退出线程 |
参数 |
value_ptr: 用户定义的指针,用来存储被等待线程的返回值地址 |
返回值 |
0:成功 其他:失败 |
例子
#include <pthread.h> static pthread_t thread; static void* thread_entry(void* parameter) { int cnt = 0; int data = (int) parameter; while (1) { printf("data : %d, cnt : %d\n", data, cnt++); sleep(5); pthread_exit(NULL); //退出线程 } printf("thread exited!\n"); return NULL; } int application_init() { int ret; int data1 = 1; /** 创建线程*/ ret = pthread_create(&thread, NULL, thread_entry, (void*)data1); if(0 != ret) printf("pthread_create failed! error code is %d\n", ret); return 0; }
7.9.3. 消息队列(Queue)
创建消息队列
函数 |
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr); |
---|---|
描述 |
创建消息队列 |
参数 |
name : 消息队列名称 oflag :消息队列打开方式 mode : attr : |
返回值 |
非NULL:返回消息队列句柄 NULL:失败 |
发送消息
函数 |
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); |
---|---|
描述 |
发送消息 |
参数 |
mqdes : 消息队列句柄 msg_ptr :指向要发送的消息的指针 msg_len : 发送的消息的长度 msg_prio : 不支持,忽略 |
返回值 |
0:成功 其他:失败 |
接收消息
例子
static mqd_t mqID; //发送线程 static void *thread_send(void *args) { char msg[] = "This is a message for test!"; mqd_t *sendID = (mqd_t *)args; while (1) { if (mq_send(*sendID, msg, sizeof(msg), 0) < 0) { printf("send msg err!\n"); //终止当前线程 pthread_exit(NULL); } os_time_dly(100); } return (void *)0; } //接收线程 static void *thread_rec(void *args) { char buf[128] ; mqd_t *recID = (mqd_t *)args; while (1) { if (mq_receive(*recID, buf, sizeof(buf), NULL) < 0) { printf("rec msg err!\r\n"); //终止当前线程 pthread_exit(NULL); } printf("Message received :(%s)\n", buf); } return (void *)0; } static void posix_queue_test(void) { pthread_t send; pthread_t rec; struct mq_attr mqAttr; pthread_attr_t attr = {0}; struct sched_param param; int ret; //创建消息队列 mqID = mq_open("/mQueue_test", O_RDWR | O_CREAT, 0666, NULL); //队列消息名字需要符合POSIX IPC的名字规则 if (mqID < 0) { printf("mq_open err!!!\r\n"); return; } //获取消息队列属性 if (mq_getattr(mqID, &mqAttr) < 0) { printf("mq_getattr err!!!\r\n"); return; } printf("mq_flags:%d\r\n", mqAttr.mq_flags); printf("mq_maxmsg:%d\r\n", mqAttr.mq_maxmsg); printf("mq_msgsize:%d\r\n", mqAttr.mq_msgsize); printf("mq_curmsgs:%d\r\n", mqAttr.mq_curmsgs); //初始化线程属性变量 pthread_attr_init(&attr); //设置优先级 pthread_attr_getschedparam(&attr, ¶m); param.sched_priority = 10; //设置优先级 pthread_attr_setschedparam(&attr, ¶m); //采用默认优先级时,设置为NULL ret = pthread_create(&send, &attr, thread_send, &mqID); //ret = pthread_create(&send, NULL,thread_send, &mqID); if (ret) { printf("pthread_create send error!!!\r\n"); } pthread_create(&rec, NULL, thread_rec, &mqID); if (ret) { printf("pthread_create send error!!!\r\n"); } }
7.9.4. 信号量(Semaphore)
初始化信号量
函数 |
int sem_init(sem_t *sem, int pshared, unsigned value); |
---|---|
描述 |
初始化信号量 |
参数 |
sem: 信号量句柄 pshared: 忽略 value: 信号量初始值,表示信号量资源的可用数量 |
返回值 |
0:成功 其他:失败 |
获取信号量
函数 |
int sem_wait(sem_t *sem); |
---|---|
描述 |
阻塞方式等待信号量 |
参数 |
sem: 信号量句柄 |
返回值 |
0:成功 其他:失败 |
函数 |
int sem_trywait(sem_t *sem); |
---|---|
描述 |
非阻塞方式等待信号量 |
参数 |
sem: 信号量句柄 |
返回值 |
0:成功 其他:失败 |
释放信号量
函数 |
int sem_post(sem_t *sem); |
---|---|
描述 |
释放信号量 |
参数 |
sem: 信号量句柄 |
返回值 |
0:成功 其他:失败 |
例子
static sem_t psem; static pthread_t waitSem; static pthread_t postSem; static void *thread_wait_sem(void *args) { while (1) { puts(">>>>>>>[0]thread_wait_sem : wait sem!"); sem_wait(&psem); puts(">>>>>>>[2]thread_wait_sem : get sem!"); } return (void *)0; } static void *thread_post_sem(void *args) { while (1) { os_time_dly(1000); sem_post(&psem); puts(">>>>>>>[1]thread_post_sem : post sem!"); } return (void *)0; } static void posix_sem_test(void) { int ret; ret = sem_init(&psem, 0, 0); if (ret) { puts("sem_init err!!!"); } pthread_create(&waitSem, NULL, thread_wait_sem, NULL); pthread_create(&postSem, NULL, thread_post_sem, NULL); os_time_dly(50); }
7.9.5. 互斥锁(Mutex)
初始化互斥锁
函数 |
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); |
---|---|
描述 |
初始化互斥锁 |
参数 |
mutex: 互斥锁句柄 attr: 指向互斥锁属性的指针,若该指针NULL,则使用默认的属性。 |
返回值 |
0:成功 其他:失败 |
互斥锁上锁
函数 |
int pthread_mutex_lock(pthread_mutex_t *mutex); |
---|---|
描述 |
阻塞方式给互斥锁上锁 ,如果互斥锁mutex被其他线程上锁持有,当前线程将阻塞等待。 |
参数 |
mutex: 互斥锁句柄 |
返回值 |
0:成功 其他:失败 |
函数 |
int pthread_mutex_trylock(pthread_mutex_t *mutex); |
---|---|
描述 |
非阻塞方式给互斥锁上锁 ,如果互斥锁mutex已经被上锁,当前线程不会阻塞等待,而是马上返回错误码 |
参数 |
mutex: 互斥锁句柄 |
返回值 |
0:成功 其他:失败 |
互斥锁解锁
函数 |
int pthread_mutex_unlock(pthread_mutex_t *mutex); |
---|---|
描述 |
互斥锁解锁 |
参数 |
mutex: 互斥锁句柄 |
返回值 |
0:成功 其他:失败 |
销毁互斥锁
函数 |
int pthread_mutex_destroy(pthread_mutex_t *mutex); |
---|---|
描述 |
销毁互斥锁 |
参数 |
mutex: 互斥锁句柄 |
返回值 |
0:成功 其他:失败 |
例子
static pthread_mutex_t mutex; static pthread_t p1, p2; extern void os_time_dly(int tick); static void *func1(void *arg) { char *str = (char *)arg; //获取互斥锁 pthread_mutex_lock(&mutex); while (*str != '\0') { printf("%c\n", *str); str++; } puts("\n"); //释放互斥锁 pthread_mutex_unlock(&mutex); return (void *)0; } static void *func2(void *arg) { char *str = (char *)arg; //获取互斥锁 pthread_mutex_lock(&mutex); while (*str != '\0') { printf("%c\n", *str); str++; } puts("\n"); //释放互斥锁 pthread_mutex_unlock(&mutex); return (void *)0; } static void posix_mutex_test(void) { char *str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char *str2 = "abcdefghijklmnopqrstuvwxyz"; int err; pthread_mutex_init(&mutex, NULL); if ((err = pthread_create(&p1, NULL, func1, str1)) != 0) { printf("[0]pthread_create fail\n"); } if ((err = pthread_create(&p2, NULL, func2, str2)) != 0) { printf("[1]pthread_create fail\n"); } }