Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Introduction to the basic concepts and related operations of TencentOS tiny tasks

2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "the basic concept and related operation introduction of TencentOS tiny task". In the daily operation, I believe that many people have doubts about the basic concept and related operation introduction of TencentOS tiny task. The editor has consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "introduction to basic concepts and related operations of TencentOS tiny task". Next, please follow the editor to study!

The basic concept of a task

From the point of view of the system, the task is the minimum operating unit that competes for system resources. TencentOS tiny is an operating system that supports multitasking. Tasks can use or wait for CPU, use memory space and other system resources, and run independently of other tasks. In theory, any number of tasks can share the same priority, so multiple tasks with the same priority in the ready state will share the processor in the way of time slice switching.

However, it should be noted that in TencentOS tiny, you cannot create a task K_TASK_PRIO_IDLE with the same priority as an idle task, and tasks with the same priority need to be allowed to use time slice scheduling and open TOS_CFG_ROUND_ROBIN_EN.

In short: TencentOS tiny tasks can be thought of as a collection of independent tasks. Each task runs in its own environment. Only one task is run at any one time, and it is up to the TencentOS tiny scheduler to decide which task to run. From a macro point of view, all tasks are being carried out at the same time.

The task in TencentOS is a preemptive scheduling mechanism. High-priority tasks can interrupt low-priority tasks, and low-priority tasks can only be scheduled after the high-priority tasks are blocked or terminated. At the same time, TencentOS also supports time slice round robin scheduling.

The system can support 10 priorities by default, 0~TOS_CFG_TASK_PRIO_MAX, this macro definition can be modified, the higher the priority value, the lower the priority of the task, (TOS_CFG_TASK_PRIO_MAX-(k_prio_t) 1U) is the lowest priority, assigned to idle tasks.

# define K_TASK_PRIO_IDLE (k_prio_t) (TOS_CFG_TASK_PRIO_MAX-(k_prio_t) 1U) # define K_TASK_PRIO_INVALID (k_prio_t) (TOS_CFG_TASK_PRIO_MAX) task status

There are several TencentOS tiny task states.

K_TASK_STATE_READY: the task is in the ready list, the ready task has the ability to execute, just wait for the scheduler to schedule, and the newly created task will be initialized into ready state.

K_TASK_STATE_READY: this state indicates that the task is executing, when it takes up the processor, but the task is still in the ready list. The TencentOS scheduler always chooses to run the highest priority ready task, and the moment the task is run, its task state becomes the running state.

K_TASK_STATE_SLEEP: if the task is currently dormant to give up the right to use CPU, then it can be said that the task is dormant, the task is not in the ready list, and the task is in the sleep list (or delay list).

K_TASK_STATE_PEND: a task is waiting for a semaphore, queue, or wait for an event.

K_TASK_STATE_SUSPENDED: the task is suspended and the task is not visible to the scheduler.

K_TASK_STATE_DELETED: the task ends and is deleted.

Wait timeout status (K_TASK_STATE_PENDTIMEOUT): the state in which a task is waiting for a semaphore, queue, or event to time out.

Sleep pending state (K_TASK_STATE_SLEEP_SUSPENDED): the state of a task when it is suspended during sleep.

Wait pending state (K_TASK_STATE_PEND_SUSPENDED): the state in which a task is suspended while it is waiting for a semaphore, queue, or event.

Wait timeout pending state (K_TASK_STATE_PENDTIMEOUT_SUSPENDED): a state in which a task is waiting for a semaphore, queue, or event to time out, but the task is already suspended.

/ / ready to schedule// a task's pend_list is in readyqueue#define K_TASK_STATE_READY (k_task_state_t) 0x0000// delayed Or pend for a timeout// a task's tick_list is in k_tick_list#define K_TASK_STATE_SLEEP (k_task_state_t) 0x0001// pend for something// a task's pend_list is in some pend object's list#define K_TASK_STATE_PEND (k_task_state_t) 0x0002// suspended#define K_TASK_STATE_SUSPENDED State_t) 0x0004// deleted#define K_TASK_STATE_DELETED (k_task_state_t) 0x0008// actually we don't really need those TASK_STATE below If you understand the task state deeply, the code can be much more elegant. / / we are pending, also we are waitting for a timeout (eg. Tos_sem_pend with a valid timeout Not TOS_TIME_FOREVER) / / both a task's tick_list and pend_list is not empty#define K_TASK_STATE_PENDTIMEOUT (k_task_state_t) (K_TASK_STATE_PEND | K_TASK_STATE_SLEEP) / / suspended when sleeping#define K_TASK_STATE_SLEEP_SUSPENDED (k_task_state_t) (K_TASK_STATE_SLEEP | K_TASK_STATE_SUSPENDED ) / / suspened when pending#define K_TASK_STATE_PEND_SUSPENDED (k_task_state_t) (K_TASK_STATE_PEND | K_TASK_STATE_SUSPENDED) / / suspended when pendtimeout#define K_TASK_STATE_PENDTIMEOUT_SUSPENDED (k_task_state_t) (K_TASK_STATE_PENDTIMEOUT | K_TASK_STATE_SUSPENDED) data structure ready list of maintenance tasks in TencentOS

TencentOS tiny maintains a ready list for mounting all ready tasks in the system, which is a list of type readyqueue_t with the following member variables:

Readyqueue_t karma rdyqenttypedef struct readyqueue_st {k_list_t task_list_ head [TOS _ CFG_TASK_PRIO_MAX]; uint32_t prio_ mask [K _ PRIO_TBL_SIZE]; k_prio_t highest_prio;} readyqueue_t

Task_list_head is an array of list type k_list_t. TencentOS tiny assigns a list to each priority task. The highest priority supported by the system is a priority mask array of TOS_CFG_TASK_PRIO_MAX prio_mask, which is an array of 32-bit variables, and the number of array members is determined by TOS_CFG_TASK_PRIO_MAX:

# define K_PRIO_TBL_SIZE ((TOS_CFG_TASK_PRIO_MAX + 31) / 32)

When the TOS_CFG_TASK_PRIO_MAX does not exceed 32, there is only one array member variable, that is, a 32-bit variable value, then each bit of the variable represents a priority. For example, when TOS_CFG_TASK_PRIO_MAX is 64, each bit of the prio_mask [0] variable represents a 0-31 priority, while each bit of the prio_mask [1] variable represents a 32-63 priority.

Highest_prio is the highest priority for recording the current priority list, making it easy to index task_list_head.

Delay list

Tasks related to system time will be mounted to this list, such as sleeping, waiting for semaphores, events, message queues, etc.

K_list_t kryptonite list; task control block

In a multitasking system, the execution of tasks is scheduled by the system. In order to schedule tasks smoothly, the system defines an additional task control block for each task. This task control block is equivalent to the ID card of the task, which contains all the information of the task, such as the stack pointer of the task, the name of the task, the formal parameters of the task, and so on. With this task control block, all the future operations of the system to the task can be realized through this task control block. The TencentOS task control block is as follows:

Typedef struct k_task_st {k_stack_t * sp; / * *

< 任务栈指针,用于切换上下文*/#if TOS_CFG_OBJECT_VERIFY_EN >

0u knl_obj_t knl_obj; / * *

< 只是为了验证,测试当前对象是否真的是一项任务。*/#endif char *name; /**< 任务名称 */ k_task_entry_t entry; /**< 任务主体 */ void *arg; /**< 任务主体形参 */ k_task_state_t state; /**< 任务状态 */ k_prio_t prio; /**< 任务优先级 */ k_stack_t *stk_base; /**< 任务栈基地址 */ size_t stk_size; /**< 任务栈大小 */ k_tick_t tick_expires; /**< 任务阻塞的时间 */ k_list_t tick_list; /**< 延时列表 */ k_list_t pend_list; /**< 就绪、等待列表 */#if TOS_CFG_MUTEX_EN >

0u k_list_t mutex_own_list; / * *

< 任务拥有的互斥量 */ k_prio_t prio_pending; /*< 用于记录持有互斥量的任务初始优先级,在优先级继承中使用 */#endif pend_obj_t *pending_obj; /**< 记录任务此时挂载到的列表 */ pend_state_t pend_state; /**< 等待被唤醒的原因(状态) */#if TOS_CFG_ROUND_ROBIN_EN >

0u k_timeslice_t timeslice_reload; / * *

< 时间片初始值(重装载值) */ k_timeslice_t timeslice; /**< 剩余时间片 */#endif#if TOS_CFG_MSG_EN >

0u void * msg_addr; / * *

< 保存接收到的消息 */ size_t msg_size; /**< 保存接收到的消息大小 */#endif#if TOS_CFG_EVENT_EN >

0u k_opt_t opt_event_pend; / * *

< 等待事件的的操作类型:TOS_OPT_EVENT_PEND_ANY 、 TOS_OPT_EVENT_PEND_ALL */ k_event_flag_t flag_expect; /**< 期待发生的事件 */ k_event_flag_t *flag_match; /**< 等待到的事件 */#endif} k_task_t;创建任务 在TencentOS tiny中,凡是使用__API__ 修饰的函数都是提供给用户使用的,而使用__KERNEL__修饰的代码则是给内核使用的。 TencentOS的创建任务函数有好几个参数: |参数| 含义 | |--|--| |task | 任务控制块 | |name | 任务名字 | |entry | 任务主体 | |arg | 任务形参 | |prio | 优先级 | |stk_base | 任务栈基地址 | |stk_size | 任务栈大小 | |timeslice | 时间片 | 参数详解(来源TencentOS tiny开发指南): task 这是一个k_task_t类型的指针,k_task_t是内核的任务结构体类型。注意:task指针,应该指向生命周期大于待创建任务体生命周期的k_task_t类型变量,如果该指针指向的变量生命周期比待创建的任务体生命周期短,譬如可能是一个生命周期极端的函数栈上变量,可能会出现任务体还在运行而k_task_t变量已被销毁,会导致系统调度出现不可预知问题。 name 指向任务名字符串的指针。注意:同task,该指针指向的字符串生命周期应该大于待创建的任务体生命周期,一般来说,传入字符串常量指针即可。 entry 任务体运行的函数入口。当任务创建完毕进入运行状态后,entry是任务执行的入口,用户可以在此函数中编写业务逻辑。 arg 传递给任务入口函数的参数。 prio 任务优先级。prio的数值越小,优先级越高。用户可以在tos_config.h中,通过TOS_CFG_TASK_PRIO_MAX来配置任务优先级的最大数值,在内核的实现中,idle任务的优先级会被分配为TOS_CFG_TASK_PRIO_MAX - 1,此优先级只能被idle任务使用。因此对于一个用户创建的任务来说,合理的优先级范围应该为[0, TOS_CFG_TASK_PRIO_MAX - 2]。另外TOS_CFG_TASK_PRIO_MAX的配置值必需大于等于8。 stk_base 任务在运行时使用的栈空间的起始地址。注意:同task,该指针指向的内存空间的生命周期应该大于待创建的任务体生命周期。stk_base是k_stack_t类型的数组起始地址。 stk_size 任务的栈空间大小。注意:因为stk_base是k_stack_t类型的数组指针,因此实际栈空间所占内存大小为stk_size * sizeof(k_stack_t)。 timeslice 时间片轮转机制下当前任务的时间片大小。当timeslice为0时,任务调度时间片会被设置为默认大小(TOS_CFG_CPU_TICK_PER_SECOND / 10),系统时钟滴答(systick)数 / 10。 创建任务的实现如下:首先对参数进行检查,还要再提一下:在TencentOS中,不能创建与空闲任务相同优先级的任务K_TASK_PRIO_IDLE。然后调用cpu_task_stk_init函数将任务栈进行初始化,并且将传入的参数记录到任务控制块中。如果打开了TOS_CFG_ROUND_ROBIN_EN 宏定义,则表示支持时间片调度,则需要配置时间片相关的信息timeslice 到任务控制块中。然后调用task_state_set_ready函数将新创建的任务设置为就绪态K_TASK_STATE_READY,再调用readyqueue_add_tail函数将任务插入就绪列表k_rdyq中。如果调度器运行起来了,则进行一次任务调度。 个人感觉吧,没有从堆中动态分配还是有点小小的遗憾,我更喜欢简单的函数接口~! 代码如下: __API__ k_err_t tos_task_create(k_task_t *task, char *name, k_task_entry_t entry, void *arg, k_prio_t prio, k_stack_t *stk_base, size_t stk_size, k_timeslice_t timeslice){ TOS_CPU_CPSR_ALLOC(); TOS_IN_IRQ_CHECK(); TOS_PTR_SANITY_CHECK(task); TOS_PTR_SANITY_CHECK(entry); TOS_PTR_SANITY_CHECK(stk_base); if (unlikely(stk_size < sizeof(cpu_context_t))) { return K_ERR_TASK_STK_SIZE_INVALID; } if (unlikely(prio == K_TASK_PRIO_IDLE && !knl_is_idle(task))) { return K_ERR_TASK_PRIO_INVALID; } if (unlikely(prio >

K_TASK_PRIO_IDLE) {return Karma err é r é TASKTASKS PRIOINVALID;} task_reset (task); # if TOS_CFG_OBJECT_VERIFY_EN > 0u knl_object_init (& task- > knl_obj, KNL_OBJ_TYPE_TASK); # endif task- > sp = cpu_task_stk_init ((void *) entry, arg, (void *) task_exit, stk_base, stk_size); task- > entry = entry Task- > arg = arg; task- > name = name; task- > prio = prio; task- > stk_base = stk_base; task- > stk_size = stk_size;#if TOS_CFG_ROUND_ROBIN_EN > 0u task- > timeslice_reload = timeslice; if (timeslice = = (k_timeslice_t) 0u) {task- > timeslice = karma robindefaulttimeslicense;} else {task- > timeslice = timeslice } # endif TOS_CPU_INT_DISABLE (); task_state_set_ready (task); readyqueue_add_tail (task); TOS_CPU_INT_ENABLE (); if (tos_knl_is_running ()) {knl_sched ();} return Knowerr destroy None;} Task destruction

This function is very simple. It controls the task to be destroyed according to the task passed in, or it can be passed into NULL to destroy the currently running task. However, it is not allowed to destroy the idle task k_idle_task, and if the scheduler cannot destroy itself when the scheduler is locked, a K_ERR_SCHED_LOCKED error code will be returned. If a mutex is used, the mutex will be released when the task is destroyed, and it will be removed from the corresponding status list according to the state in which the task is destroyed, such as ready state, delayed state, and waiting state. The code is implemented as follows:

_ _ API__ k_err_t tos_task_destroy (k_task_t * task) {TOS_CPU_CPSR_ALLOC (); TOS_IN_IRQ_CHECK (); if (unlikely (! task)) {task = kicking curry task;} # if TOS_CFG_OBJECT_VERIFY_EN > 0u if (! knl_object_verify (& task- > knl_obj, KNL_OBJ_TYPE_TASK)) {return K_ERR_OBJ_INVALID } # endif if (knl_is_idle (task)) {return KnowledgeTASKTASKDESTROYIDLED;} if (knl_is_self (task) & & knl_is_sched_locked ()) {return KnowledgeSCHEDLOCKED;} TOS_CPU_INT_DISABLE (); # if TOS_CFG_MUTEX_EN > 0u / / when we die, wakeup all the people in this land. If (! tos_list_empty (& task- > mutex_own_list)) {task_mutex_release (task);} # endif if (task_state_is_ready (task)) {/ / that's simple, good kid readyqueue_remove (task);} if (task_state_is_sleeping (task)) {tick_list_remove (task) } if (task_state_is_pending (task)) {pend_list_remove (task);} task_reset (task); task_state_set_deleted (task); TOS_CPU_INT_ENABLE (); knl_sched (); return task sleep

Task sleep is very simple. The main idea is to remove the task from the ready list and add k_tick_list to the delay list. If the scheduler is locked, it directly returns the error code K_ERR_SCHED_LOCKED. If the sleep time is 0, call the tos_task_yield function to initiate a task schedule; call the tick_list_add function to insert the task into the delay list, and the sleep time delay is specified by the user. However, it should be noted that if the task sleep time is permanent sleep TOS_TIME_FOREVER, the error code K_ERR_DELAY_FOREVER will be returned. This is because task sleep is an active behavior. If you sleep permanently, you will not be able to wake up actively, while task waiting events, semaphores, message queues and other behaviors are passive and can be permanent waiting. Once the event occurs, the semaphore is released, and the message queue is not empty, the task will be awakened. This is passive behavior, and these two points need to be distinguished. Finally, you can switch another task by calling the readyqueue_remove function to remove the task from the ready list, and then calling the knl_sched function to initiate a task schedule. The code for task sleep is as follows:

_ _ API__ k_err_t tos_task_delay (k_tick_t delay) {TOS_CPU_CPSR_ALLOC (); TOS_IN_IRQ_CHECK (); if (knl_is_sched_locked ()) {return unlikely (delay = = (k_tick_t) 0u) {tos_task_yield (); return K_ERR_NONE } TOS_CPU_INT_DISABLE (); if (tick_list_add (k_curr_task, delay)! = K_ERR_NONE) {TOS_CPU_INT_ENABLE (); return readyqueue_remove (k_curr_task); knl_sched (); return K_ERR_NONE At this point, the study of "introduction to the basic concepts and related operations of TencentOS tiny tasks" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report