首页 > 代码库 > Kithara RTS的多任务编程

Kithara RTS的多任务编程

笔者理解:Kithara RTS的多任务编程主要用于内核实时程序开发中,其体系结构比较像一些嵌入式实时操作系统,如ucos,freertos等。笔者翻译了一部分内容,有一些内容看原文更好理解,因此没有翻译。

Tasks

The Multitasking Module offers task execution on kernel-level and user-level. On kernel-level a preemptive scheduling is implemented. The scheduling is priority controlled. As a result a task can never be interrupted by another task with a lower priority. On the other side a lower priority task can be interrupted by a higher priority task. The implemented preemptive scheduling on kernel-level does not have the restrictions of the cooperative scheduling on user-level like described below.

多任务模块提供在内核层和用户层执行任务。在内核层任务是被抢占式调度执行的。调度机制具有优先级控制。高优先级的任务不会被低优先级的任务中断,低优先级的任务会被高优先级的任务中断。内核层和用户层的任务之间是相互独立,不存在优先级高低关系。

On user-level tasks are managed with a cooperative scheduling. As a result a running task can only be switched at synchronization points like events or semaphores. Another option is that the running task yields itself to give the scheduler the opportunity to schedule another task. If a task is not cooperative by yielding itself or wait at a synchronization object, no other task can be scheduled as long as the task is running. An advantage for tasks on user-level is the possibility of debugging and the handling is much easier than for standard Windows threads.

在用户层,任务调度是采取协调调度机制。一个正在运行的任务只能在事件或信号量被触发时才能运行。另一方面,正在运行的任务可以将自身挂起,让其他任务执行。

在用户层的任务调度机制在调试和检错方面比标准的windows线程更加容易使用。

Another option is to divide tasks to different CPUs. This is possible with the multi-core support. Tasks, interrupts and timers can be assigned to multiple CPUs cores. With the “Dedicated” real-time mode it is possible to use CPU cores exclusively without Windows influence. As a result extreme real-time capabilities can be archived. For further information see Setting target processor.

对于多核平台,可以将不同的任务分配给不同的CPU。任务,中断和定时器也可也同时被分配个多个CPU.(即任务和CPU之间是多对多的关系)

使用“Dedicated”实时模式,可以让CPU独立运行不被windows干扰。这样可以获取非常好的实时性能。更多的信息可以查看“Setting target processor”部分。

The tasks are priority controlled with 255 levels. Mind that a unlimited number of tasks is possible per level. The scheduler operates with a round-robin algorithm per level, i.e. the tasks are organized in a priority queue (FIFO, first in - first out). If a task run to its end or is switched, the next task with the same priority in the queue gets execution time. The scheduler takes priorities into account per CPU core, e.g. a task with a lower priority can run on a specific CPU core without being interrupted by higher priority tasks on another CPU core.

任务优先级具有255个级别,每个优先级又可以被多个任务共享(不限数量),同一优先级的任务采取循环调度的策略。

To synchronize tasks the synchronization objects semaphore, quickmutex and event are provided.

可以使用这些对象实现任务之间的同步,semaphore,quickmutex和event.

Tasks can inherit priorities while requesting task semaphores. Furthermore dynamic priorities are supported, i.e. the task can be blocked or started depending on changing the priority of other tasks.

任务在等待任务semaphore时可以继承优先级。也支持动态优先级调整。例如可以通过改变任务优先级使任务被阻塞或开启。

In contrast to Windows threads a task can be easily rescheduled using the function KS_triggerTask. At the end of the executed code a task can re-trigger itself again.

与Windows的线程调度机制相比,一个任务通过KS_triggerTask被重新激活调度。任务也可以自身重新激活自身。

There are some interesting realtimer features in conjunction with tasks. Timers are executed as tasks and several timers can control several tasks at the same time. The scheduler controls the code execution with priorities.

定时器与任务机制有一定类似。

For timers no base resolution is used, i.e. the timer is programed to the next desired point in time. At the same time clocks and timers are kept synchronous - there is no drifting apart. The best timer source is selected for every hardware automatically.

Realtimers support frequencies up to 100 kHz and every timer is handled on each CPU independently. Cyclic and one-shot timers are possible options.

In conjunction with tasks the concept of step programming is potentially interesting. The application is divided in several completed steps. Each step is assigned to one task. If one task is completed, a timer is programed to start the next task.

Another feature of realtimers is to adjust the timer on the flow, e.g. increment the timer period by a small amount.

Last but not least multiple timers can be started synchronously. This can be done with the functionKS_startTimerDelayed. A absolute start time or a relative start delay can be provided. To start multiple timers at the same time a absolute start time can be programmed for multiple timers.

使用KS_startTimerDelayed函数可以使多个定时器被同时开启。

Creating a task----创建任务

To create a task the function KS_createTask can be used. As parameters a callback handle and a priority is needed. With the flag KSF_DONT_START the task will not start until KS_triggerTask is called.

使用KS_createTask创建任务,参数包括回调函数句柄、优先级和标志位。如果标志位设置为KSF_DONT_START,则任务不会被执行,直到使用KS_triggerTask触发该任务。

Working with tasks----运行任务

Task operations are trigger, suspend, resume, yield, sleep, exit and kill.

任务可以被触发、挂起、回复、让位、休眠、退出和关闭。

For task operations the functions KS_triggerTask, KS_suspendTask, KS_resumeTask, KS_yieldTask,KS_sleepTask, KS_exitTask and KS_killTask are provided.

对应的使用以上几种函数实现任务操作。

The function KS_triggerTask cannot interrupt a running task. A task will be (re-)triggered from the statesdormant or suspend|dormant.

KS_triggerTask无法中断一个正在运行的任务。如果任务处于休眠或挂起状态,那么其将会被触发。

Furthermore a task can be suspended and resumed again. A task can yield to another task on the same priority level. If no task with the same priority exists the highest task that just became ready is used.

任务可以被反复挂起和回复。一个任务可以把运行权转让给同等优先级的其他任务。如果不存在同等优先级的任务,那么将会使已经准备就绪的最高优先级的任务运行。

Calling the function KS_sleepTask the scheduler will delay the task for the given period of time.

KS_sleepTask会使任务执行过程中休眠一段时间然后恢复。

There are two ways to end a task: exit and kill. If KS_exitTask is called then the task exits at once, but can be triggered again. The function KS_killTask kills a task ultimately. The task cannot be triggered again.

停止一个任务有两种方式,一种是退出任务,一种是关闭任务。使用KS_exitTask 时,任务将会被立刻退出,但是可以被重新激活。使用KS_killTask可以强制关闭一个任务,这个任务不会被重新激活。

With the function KS_getTaskState one of the task states (dormant, ready, running, waiting andsuspended) can be queried.

使用KS_getTaskState可以获得一个任务的状态,这些任务包括(dormant, ready, running, waiting andsuspended)。

To set set task‘s stack size, the function KS_setTaskStackSize can be used.

通过KS_setTaskStackSize来设置任务堆栈大小。

Setting priorities----设置优先级

The function KS_setTaskPrio sets the task priority. Priorities from 1..31 are called idle and from 32..255 are called normal.

使用KS_setTaskPrio设置任务优先级。1-31级优先级为空闲优先级,32-255为普通优先级。

Tasks with idle priorities can be interrupted by Kithara system tasks. If using the “Dedicated” real-time mode with at least one core reserved for Windows, this can be ignored.

空闲优先级的任务可以被kithara系统任务中断。如果使用“Dedicated”实时模式,这可以被忽略。

If high priority task using all system time and e.g. Windows cannot get a minimum of time, a BSOD will be registered! One way to counter this is to use idle priorities. A cyclic task which do not need all system time is no problem, too. Last but not least step programming with little delays can be used.

如果高优先级的任务占用了系统的所有时间,那么windows由于不会获得时间片,因此会蓝屏。一种解决方法是使用idle优先级。一个循环执行的任务但是不占用所有系统时间是没有问题的。

Setting target processor and getting current context information----设置目标处理器和获取当前内容信息

With the function KS_setTargetProcessor the target processor for the current thread or task is set. Every resource (e.g. interrupts, callbacks, timer, task and so on) which is created inside a task or thread after calling this function will be assigned to the specified logical processor.

使用KS_setTargetProcessor函数设置任务运行在指定的处理器上。

In that way the computational load can not even be divided in different tasks but also assigned to different CPU cores. This option is available for normal and “Dedicated” CPUs.

这样的话计算负载将不会被分配到多个任务上和多个处理器上。

The counting of the target processor starts with the first shared/Windows CPU(s) followed by “Dedicated” CPU(s). For Windows 8 no shared CPUs exist but Windows CPUs instead. The number of shared/Windows CPUs and “Dedicated” CPUs can be configured in Windows (see Setup dedicated CPUs).

 

If a task or thread is running, its current used processor number can be queried with the functionKS_getCurrentProcessor. With the flag KSF_NUM_PROCESSORS it is possible to only get the number of real-time processors.

可以使用KS_getCurrrentProcessor查询当前任务正在使用的处理器。

To get information about the current execution context the function KS_getCurrentContext can be used. It delivers the structure KSContextInformation. Next to the current level, information about the task like task handle, priority, current logical processor number and stack information is delivered.

使用KS_getCurrentContent可以获得当前执行体的信息。

Synchronizing tasks----任务同步

If multiple tasks share a common resource, task synchronization is usually needed (reader/writer problem). Three synchronization objects are provided: events, quickmutexes and semaphores.

如果多个任务共用一个资源,那么任务同步是必须的。有三种对象适用于同步机制,event,quickmutex,semaphore

The Event and the quickmutex are already handled in another tutorial. Let‘s look at semaphores.

Event和quickmutex将会在另一个文档中说明,这里只看一下semaphore

Semaphores can only be requested by real-time tasks. In contrast to quickmutexes, a semaphores has no ownership, i.e. a semaphore can be unlocked by any running task.

Semaphore只能由实时任务使用,与quickmutex相比,semaphore没有拥有权,例如semaphore可以被任何任务阻止。

Creating a semaphore----创建semaphore

A semaphore can be created with the function KS_createSemaphore. As parameters a maximum count and an initial count is needed. The maximum count specifies the number of requests needed (resources to share), until the semaphores blocks. The maximum count must be greater than one. With the initial count a starting value can be set. The value must be less or equal to the maximum count.

Requesting or releasing a semaphore----请求和释放semaphore

Semaphores have two operations: request and release. To execute these operations the functionsKS_requestSemaphore and KS_releaseSemaphore can be used.

To request a semaphore a semaphore handle and a timeout is needed. The timeout is given in 100-ns-units.

If the semaphore is free, then the internal counter is decreased by one and the task continues to run. Otherwise, the task will be blocked until the semaphore is free again.

For requesting semaphores the concept of priority inheritance comes into play. If the task already requested the semaphore has a lower priority than the task requesting the semaphore, the requesting task inherits the higher priority from the task already requested the semaphore. As a result the requesting task can run with the inherited, higher priority.

To release a semaphore only a semaphore handle is needed. The function KS_releaseSemaphore increases the internal counter until the maximum count is reached. If other tasks are waiting that requested the semaphore, the task with the highest priority is set to ready.

Removing a semaphore----删除信号量

To remove a semaphore and release all its resources the function KS_removeSemaphore must be used.

使用KS_removeSemaphore来删除信号量及其使用的资源。

Removing a task----删除任务

To remove a task and free all its resources the function KS_removeTask must be used.

使用KS_removeTask来删除一个任务及其资源。

Every task that has been created with KS_createTask must be removed. This is true for tasks that have been killed with KS_killTask, too.

使用KS_createTask创建的任务最后必须被删除。那些被KS_killTask的任务也需要被删除。

Task states and transitions----任务的状态与切换

The following diagram shows all task states (dormant, ready, running, waiting and suspended) with the transitions each KS-function causes.

下面的状态图表显示了任务状态切换关系。

State machine of the task module