| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 物联网操作系统Zephyr(内核篇)之2.0 内核服务之线程(1) -> 正文阅读 |
|
[Java知识库]物联网操作系统Zephyr(内核篇)之2.0 内核服务之线程(1) |
目录 1.生命周期1.1 线程创建线程创建后,内核初始化线程控制块以及线程堆栈尾部,线程其余部分通常不初始化。 如果指定的启动延时是 如果延迟启动的线程还未启动,内核可以取消该线程。如果线程已经启动了,则内核在尝试取消它时不会有如何效果。如果延迟启动的线程被成功地取消了,它必须被再次创建后才能再次使用。 1.2.线程的正常结束线程一旦启动,它通常会一直运行下去。不过,线程也可以从它的入口点函数中返回,从而同步结束执行。这种结束方式叫做 正常结束(terminaltion)。 正常结束的线程需要在返回前释放它所拥有的共享资源(例如互斥量、动态分配的内存)。内核 不会 自动回收这些资源。 在某些情况下,一个线程可能希望休眠,直到另一个线程终止。这可以通过k_thread_join() API来实现。这将一直阻止调用线程直到超时结束,目标线程自退出或目标线程中止(由于k_thread_abort()调用或触发致命错误)。 一旦线程终止,内核保证不会使用该线程结构。这样一个结构的内存可以被重用用于任何目的,包括生成一个新线程。注意,线程必须完全终止,这表示了竞争条件,即线程自己的逻辑信号完成,在内核处理完成之前被另一个线程看到完成。在正常情况下,应用程序代码应该使用k_thread_join()或k_thread_abort()来同步线程终止状态,而不依赖于来自应用程序逻辑内部的信号量。 1.3.线程的异常终止线程可以通过?异常终止 (aborting)?异步结束其执行。如果线程触发了一个致命错误(例如引用了空指针),内核将自动终止该线程。 其它线程(或线程自己)可以调用? 线程终止时,内核不会自动回收该线程拥有的共享资源。 1.4.线程挂起如果一个线程被挂起,它将在一段不确定的时间内暂停执行。函数? 线程一旦被挂起,它将一直不能被调度,除非另一个线程调用?
2.?线程状态ready:没有其他因素影响线程执行,它处于准备状态。 unready具有一个或多个阻止其执行的因素的线程将被视为未准备好,并且不能被选择为当前线程。 以下因素会使线程未准备好:
3.线程堆栈对象每个线程都需要它自己的堆栈缓冲区,以便CPU推送上下文。根据配置的不同,必须满足若干约束条件:
对齐约束可能是相当严格的,例如一些mpu要求它们的区域大小为2的幂,并与自己的大小对齐。 因此,可移植的代码不能简单地将任意的字符缓冲区传递给k_thread_create()。有一个特殊的宏来实例化堆栈,前缀为K_KERNEL_STACK和K_THREAD_STACK。 ?4.?仅内核堆栈如果知道线程永远不会在用户模式下运行,或者堆栈被用于特殊上下文,如处理中断,最好使用K_KERNEL_STACK宏定义堆栈。这些堆栈节省了内存,因为MPU区域将永远不需要被编程来覆盖堆栈缓冲区本身,而且内核将不需要为特权提升堆栈或仅属于用户模式线程的内存管理数据结构预留额外的空间。 尝试从用户模式中使用以这种方式声明的堆栈将导致调用者出现致命错误。 如果未启用CONFIG_USERSPACE,则K_THREAD_STACK宏集与K_KERNEL_STACK宏具有相同的效果。 5.线程堆栈如果已知堆栈需要托管用户线程,或者如果无法确定这一点,请使用K_THREAD_STACK宏定义堆栈。这可能会使用更多的内存,但堆栈对象适用于托管用户线程。 如果未启用CONFIG_USERSPACE,则K_THREAD_STACK宏集与K_KERNEL_STACK宏具有相同的效果。 6.线程优先级线程的优先级是一个整数值,并且可以是负值或非负值。数值上较低的优先级优先于数值上较高的值。例如,调度器给予优先级4的线程A比优先级7的线程B更高的优先级;优先级-2的线程C比线程A和线程B具有更高的优先级。 调度程序根据每个线程的优先级来区分两类线程。
线程的初始优先级值可以在线程启动后进行向上或向下的更改。因此,通过改变优先级,抢占线程可能成为一个协作线程,反之亦然.
?该内核支持几乎无限数量的线程优先级级别。配置选项CONFIG_NUM_COOP_PRIORITIES和CONFIG_NUM_PREEMPT_PRIORITIES指定每个线程类的优先级数,从而产生以下可用的优先级范围:
?例如,配置5个合作优先级和10个优先级优先级分别导致范围为-5到-1和0到9。 Meta-IRQ 优先级 启用时(请参见CONFIG_NUM_METAIRQ_PRIORITIES),在优先级空间的最高(数值最低)端处有一个特殊的协作优先级子类:MetaIRQ线程。它们是根据它们的正常优先级进行调度的,但也具有特殊的优先级抢占所有其他线程(和其他元irq线程),即使这些线程是协作的和/或已经采取了调度程序锁定。然而,Meta-IRQ线程仍然是线程,并且仍然可以被任何硬件中断中断。 ?这种行为使得解除解除Meat-irq线程的行为(通过任何方式,例如创建它、调用k_sem_give()等。在低优先级线程完成时的同步系统调用,或者从真中断上下文完成时类似arm的“挂起的IRQ”。其目的是,该特性将用于实现驱动程序子系统中的中断“下半部分”处理和/或“小任务”特性。该线程一旦被唤醒,将保证在当前CPU返回到应用程序代码之前运行。 与其他操作系统中的类似特性不同,meta-IRQ线程是真正的线程,并且运行在它们自己的堆栈上(必须正常分配),而不是每个cpu的中断堆栈。支持在受支持的架构上使用IRQ堆栈的设计工作正在进行中。
?6.线程选项内核支持一系列?线程选项(thread options),以允许线程在特殊情况下被特殊对待。这些与线程关联的选项在线程创建时就被指定了。 不需要任何线程选项的线程的选项值是零。如果线程需要选项,您可以通过选项名指定。如果需要多个选项,使用符号? 支持以下线程选项。?
K_ESSENTIAL
此选项会将该线程标记为一个基本的线程。这将指示内核将线程的终止或中止视为一个致命的系统错误。默认情况下,线程不被认为是基本线程。?
K_FP_REGS和K_SSE_RGES
这两个选项是 x86 相关的选项,分别表示线程使用 CPU 的浮点寄存器和 SSE 寄存器,指示内核在调度线程进行时需要采取额外的步骤来保存/恢复这些寄存器的上下文。 默认情况下,内核在调度线程时不会保存/恢复这些寄存器的上下文. K_USER 如果启用了CONFIG_USERSPACE,这个线程将在用户模式下创建,并且将拥有减少的特权。请参见用户模式。否则,此标志将无任何作用。 K_INHERIT_PERMS 如果启用了CONFIG_USERSPACE,此线程将继承父线程拥有的所有内核对象权限,但父线程对象除外。请参见用户模式。 7.线程自定义数据每个线程都有一个32位的自定义数据区域,只有线程本身可以访问,应用程序可以用于它选择的任何目的。线程的默认自定义数据值为零。
默认情况下,将禁用线程自定义数据支持。配置选项CONFIG_THREAD_CUSTOM_DATA可用于启用支持。 k_thread_custom_data_set()和k_thread_custom_data_get()函数分别用于写入和读取线程的自定义数据。一个线程只能访问它自己的自定义数据,而不能访问其他线程的数据。? 下面的代码使用自定义数据特性来记录每个线程调用一个特定例程的次数。
使用线程自定义数据允许例程访问线程特定的信息,通过使用自定义数据作为指向线程拥有的数据结构的指针。 8.线程实现创建一个线程通过定义其堆栈区及其线程控制块,然后调用k_thread_create()来生成一个线程。栈区域是一个由字节构成的数组,且其大小必须等于? 必须使用K_THREAD_STACK_DEFINE或K_KERNEL_STACK_DEFINE定义堆栈区域,以确保它在内存中正确设置。 堆栈的size参数必须为以下三个值之一:
线程生成函数返回其线程id,可用于引用该线程。 下面的代码会生成一个立即启动的线程。
或者,也可以通过在编译时调用K_THREAD_DEFINE来声明一个线程。请注意,宏会自动定义堆栈区域、控制块和线程id变量。 下面的代码与上面的代码段具有相同的效果。
用户模式约束?此部分仅适用于启用CONFIG_USERSPACE,并且用户线程尝试创建新线程。k_thread_create()API仍然在使用,但是必须满足一些额外的约束,否则调用线程将被终止:
删除权限如果启用了CONFIG_USERSPACE,那么在监控模式下运行的线程可以使用k_thread_user_mode_enter()API执行到用户模式的单向转换。这是一个单向的操作,它将重置和零的线程的堆栈内存。该螺纹将被标记为非必要的。 终止线程一个线程通过从其入口点函数返回来终止自己。下面的代码说明了线程可以终止的方式
如果启用了CONFIG_USERSPACE,中止一个线程将另外将线程和堆栈对象标记为未初始化,以便它们可以被重用。 运行时统计信息如果启用了CONFIG_THREAD_RUNTIME_STATS,则可以收集和检索线程运行时统计信息,例如,一个线程的执行周期的总数。 默认情况下,运行时统计信息是使用默认的内核计时器来收集的。对于某些架构、SoCs或板,有通过计时功能具有更高分辨率的计时器。使用这些计时器可以通过CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS.来启用 下面是一个示例:
建议的用途使用线程来处理在ISR中无法处理的处理。 使用单独的线程来处理可以并行执行的逻辑上不同的处理操作。 配置选项相关配置选项:
9.API参考宏定义
K_ESSENTIAL:不能中止的系统线程。
K_FP_REGS :FPU寄存器由上下文交换机进行管理。此选项表示线程使用CPU的浮点寄存器。这将指示内核在调度线程时采取其他步骤来保存和恢复这些寄存器的内容。如果未启用CONFIG_FPU_SHARING,则无效。
K_USER:用户模式线程——此线程已从监控模式降到用户模式,因此有额外的限制。
K_INHERIT_PERMS :继承权限——指示正在创建的线程应该继承来自创建它的线程的所有内核对象权限。如果未启用CONFIG_USERSPACE,则无效。
K_CALLBACK_STATE:回调项目状态——这是为“回调管理器”实用程序(最初是p4wq)保留的单位状态,它们需要跟踪从用户提供的回调中调用的调用操作。实际上,它充当了一个很小的零开销TLS数据。
k_thread_access_grant(
thread, ...):授予对一组内核对象的线程访问权限。这是一个方便的功能。对于所提供的线程,授予对其余参数的访问权限,这些参数必须是指向内核对象的指针。线程对象必须被初始化(即正在运行)。这些对象不需要是。请注意,NULL不应该作为参数传递。
K_THREAD_DEFINE(name, stack_size, entry, p1, p2, p3, prio, options, delay) 静态地定义和初始化一个线程。 线程可能被计划立即执行或延迟启动。 线程选项是特定于架构的,可以包括K_ESSENTIAL、K_FP_REGS和K_SSE_REGS。可以通过使用“|”(逻辑OR运算符)来分离它们来指定多个选项。 线程的ID可以使用:
Typedefs ?
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 22:53:26- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |