Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
ART-Pi Smart
POSIX
【ART-PI Smart 抛砖引玉 二】基于POSIX的应用开发之多线程
发布于 2022-05-11 23:29:18 浏览:878
订阅该版
#POSIX简介与选择分析 POSIX:可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),是IEEE(电气与电子工程师协会)协会发布的一种操作系统通用化函数接口,用来在应用层实现开发的统一。主要是为了解决早年类Unix系统很多版本之间函数接口不能统一导致的很多开发上的不便。 经过多年的发展,在Uinx/Liunx系统发展过程中,posix系统进一步趋于完善,发展至今,尤其是在linux上,作为应用开发的通用API,具备了较高的可移植性和兼容性,几乎成为了现代操作系统应用开发API的标配。所以,与其说 POSIX 是一个东西,不如说是一个标签。想象一下,有一个盒子,上面贴着标签:POSIX,而盒子里是一个标准。 RT-Smart操作系统具备RT自身的一套完善的API,在应用开发过程中,尤其是之前按熟悉RT-Thread系统开发工程师们,在切换成Smart之后不会有任何的突兀和不适,RT自家的两个系统之间接口是高度统一的。但是对于选择使用Smart系统的工程师来说,最大的动力就是Smart的混合微内核的高效特性,可以用来替代庞大的linux,这种情况下,在linux上之前开发的应用程序,移植到Smart上的时候,只要接口是POSIX标准,那么理论上就可以在用户态直接编译运行elf文件,而不必再用RT的接口标准对程序进行重写。这将大大减少程序移植的复杂度。因此从本篇开始,将会针对POSIX接口进行几个常用模块的程序编写与运行工作,来测试一下Smart对POSIX接口的应用程序支持情况。 #POSIX线程pthread api的应用 POSIX标准下对线程的操作常用的基本API接口包括下面几个: - pthread_create() 创建线程开始运行相关线程函数,运行结束则线程退出 - pthread_eixt() 因为exit()是用来结束进程的,所以则需要使用特定结束线程的函数 - pthread_join() 挂起当前线程,用于阻塞式地等待线程结束,如果线程已结束则立即返回,0=成功 - pthread_cancel() 发送终止信号给thread线程,成功返回0,但是成功并不意味着thread会终止 - pthread_testcancel() 在不包含取消点,但是又需要取消点的地方创建一个取消点,以便在一个没有包含取消点的执行代码线程中响应取消请求. - pthread_setcancelstate() 设置本线程对Cancel信号的反应 - pthread_setcanceltype() 设置取消状态 继续运行至下一个取消点再退出或者是立即执行取消动作 - pthread_setcancel() 设置取消状态 ##创建线程 ``` int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); ``` 函数参数: 1. pthread_t *thread, 传入创建的pthread_t指针。 2. const pthread_attr_t *attr,修改进程的属性,如果不设置则可以传入NULL 3. void *(*start_routine) (void *)创建出来的进程执行的函数,返回类型为void*,并且需要带参数void* 4. void *arg 传入的函数参数。 返回值: 1. 成功创建线程,返回0;否则返回错误码。 ##线程连结 ``` int pthread_join( pthread_t thread, void * value_ptr ); ``` 函数参数: 1. pthread_t *thread, 传入创建的pthread_t指针。 2. void *arg 传入的用来接收线程返回值的内存指针。 返回值: 1. 成功,返回0;否则返回错误码。 调用pthread_join的线程,将被挂起,直到参数thread所代表的线程终止时为止。pthread_join是一个线程阻塞函数,调用它的函数将一直等到被等待的线程结束为止。如果value_ptr不为NULL,那么线程thread的返回值存储在该指针指向的位置。该返回值可以是由pthread_exit给出的值,或者该线程被取消而返回PTHREAD_CANCELED。 ##线程分离 ``` int pthread_detach(pthread_t thread); ``` 函数参数: 1. pthread_t *thread, 传入创建的pthread_t指针。 个线程或者是可汇合(joinable,默认值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。脱离的线程却像守护进程,当它们终止时,所有相关的资源都被释放,我们不能等待它们终止。如果一个线程需要知道另一线程什么时候终止,那就最好保持第二个线程的可汇合状态 ##线程退出 ``` void pthread_exit(void * rval_ptr) ``` 函数参数: 1. rval_ptr:线程返回值,由调用pthread_join()的线程获取 调用在线程内调用此函数,相当于直接调用了return,但不同的是在线程中的任意函数调用了pthread_exit()都具有退出线程的同样效果。 ##获取线程ID ``` pthread_t pthread_self(); ``` 函数返回: 1. 返回当前调用该函数线程的ID 利用该函数,可以在某个线程内部随时获取当前所处线程的ID,方便用来进行后续更多的判断。 #pthread线程操作程序编写 程序设计流程: 利用pthread线程操作API, 创建两个线程,两个线程入口内部分别进行自身信息的打印输出,两个子线程创建之后,分别把子线程和当前主线程进行连接,此时主线程会阻塞等待两个子线程运行结束,然后正常退出。 下面给出该程序的示例,由于程序较短,直接贴在下方: ``` #include
#include
#include
#include
#include
#include
#include
static void *thread1_entry(void *arg) { printf("sub thread1 running...\r\n"); sleep(1); pthread_exit(0); return NULL; } static void *thread2_entry(void *arg) { printf("sub thread2 running...\r\n"); sleep(1); pthread_exit(0); return NULL; } int thread_create_demo(void) { pthread_t mid; pthread_t new_th; pthread_t new2_th; pthread_t new3_th; printf("\n [thread_create_demo]\r\n"); if(pthread_create(&new_th, NULL, thread1_entry, NULL) != 0) { perror("failed: Error creating thread1\r\n"); return 1; } if(pthread_create(&new2_th, NULL, thread2_entry, NULL) != 0) { perror("failed: Error creating thread2\r\n"); } if(pthread_create(&new3_th, NULL, thread2_entry, NULL) != 0) { perror("failed: Error creating thread2\r\n"); } mid = pthread_self(); printf("main thread: %d\r\n", main_th); if(pthread_join(new_th, NULL) != 0) { perror("example_pthread_create() failed: Error in pthread_join()\n"); return 1; } if(pthread_join(new2_th, NULL) != 0) { perror("example_pthread_create() failed: Error in pthread_join()\n"); return 1; } if(pthread_join(new3_th, NULL) != 0) { perror("example_pthread_create() failed: Error in pthread_join()\n"); return 1; } printf("exit.\n"); return 0; } ``` #编译与运行 代码写好后,利用scons进行编译,记得在代码目录下设置好scons编译需要用到的构建文件,具体编译环境相关的操作参考上一篇文章,[【ART-PI Smart 抛砖引玉 一】系统开发环境搭建与相关代码构建编译运行](https://club.rt-thread.org/ask/article/57c4661595a05b47.html) 编译没有错误之后,则会在sdk的userapps/root/bin目录下生成对应的elf文件。通过上一篇介绍的网口tftp,把该应用的elf文件下载到开发板的文件系统中(具体操作请参考上面第一篇的文章连接),即可运行。正常情况下,会看到程序中两个子线程和主线程对应的打印输出信息。 #总结 通过小小的线程创建例程,可以观察到,posix接口的api在Smart系统上是可以正常的支持的,后续将在线程操作的基础上,继续移植测试posix标准下IPC机制,将会以经典的生产者-消费者模型为例,来展示posix标准下的ipc运行情况。 本篇的最后,继续用一段诗来结束今天一天的疲惫吧。(●'◡'●) > “盗取荒野与星空的 人不再仰望 介乎科学和白日梦 此间诗意杀人地 煞费万物虚构之舟 去往意识碎片 不眠浪潮灰烬的意志 在酒的深处重逢” ---发光曲线乐队《荒野星》节选
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
RickFlying
something in the way
文章
10
回答
45
被采纳
0
关注TA
发私信
相关文章
1
移植rt-thread2.1.0缺少components/pthreads里的posix_types.h文件中包含的sy
2
[征集自愿者] POSIX相关章节文档编写
3
RT-Thread POSIX支持
4
POSIX标准接口针对文件系统没有导出fsync
5
POSIX接口的select还没实现?
6
pthread 组建bug反馈
7
RTT中的POSIX支持
8
RT-Thread 如何用POSIX接口
9
使用 RT_USING_POSIX finsh能显示,但不能输入
10
请教、讨论POSIX接口、dfs中的pos和size问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
10
个答案
3
次被采纳
xiaorui
3
个答案
2
次被采纳
winfeng
2
个答案
2
次被采纳
三世执戟
8
个答案
1
次被采纳
KunYi
8
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
lizimu
2
篇文章
9
次点赞
swet123
1
篇文章
4
次点赞
Days
1
篇文章
4
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部