RTOS学习笔记

一、RTOS系统配置

        总的来说,一般的发行版本的linux都不是实时系统,一般的发行版本linux准确地说是分时系统,更强调多用户的分时调用。

因次在设计的过程中,考虑的更多的是系统的并发特性,保证及时响应每个用户的任务应用处理需求。而在实时系统中,需要

保证实时任务在规定内时间完成任务,因此如何保证实时任务能够实时的执行是操作系统调度机制的核心问题。正因此可抢占式

调度策略是操作系统内核调度策略的必备选项,保证实时任务的优先级最高,一旦就绪完毕,无论系统的负载如何,都能够获取

CPU的使用权,保证实时任务执行。

       一句话总结就是:更改内核配置,把默认分时间片调度策略变为可抢占。

Getting the sources

First, the kernel version should be chosen. After this, take a look if the PREEMPT_RT patch is available for this particular version.

The source of the desired version has to be downloaded (for the Linux kernel as well as for the PREEMPT_RT patch). This example is based on the Linux kernel version 4.4.12.

$ wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.4.12.tar.xz
$ wget https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patch-4.4.12-rt19.patch.xz

After downloading, unpack the archives and patch the Linux kernel:

$ xz -cd linux-4.4.12.tar.xz | tar xvf -
$ cd linux-4.4.12
$ xzcat ../patch-4.4.12-rt19.patch.xz | patch -p1

Configuring the kernel

The only necessary configuration for real-time Linux kernel is the choice of the “Fully Preemptible Kernel” preemption model (CONFIG_PREEMPT_RT_FULL). All other kernel configuration parameters depend on system requirements. For detailed information about how to configure a kernel have a look at Linux kernel documentation.

When measuring system latency all kernel debug options should be turned off. They require much overhead and distort the measurement result. Examples for those debug mechanism are:

  • DEBUG_PREEMPT
  • Lock Debugging (spinlocks, mutexes, etc. . . )
  • DEBUG_OBJECTS

Some of those debugging mechanisms (like lock debugging) produce a randomized overhead in a range of some micro seconds to several milliseconds depending on the kernel configuration as well as on the compile options (DEBUG_PREEMPT has a low overhead compared to Lock Debugging or DEBUG_OBJECTS).

However, in the first run of a real-time capable Linux kernel it might be advisable to use those debugging mechanisms. This helps to locate fundamental problems.

Building the kernel

Building the kernel and starting the kernel works similarly to a kernel without PREEMPT_RT patch.

二、实时任务应用程序开发

HOWTO build a simple RT application

The POSIX API forms the basis of real-time applications running under PREEMPT_RT. For the real-time thread a POSIX thread is used (pthread). Every real-time application needs proper handling in several basic areas like scheduling, priority, memory locking and stack prefaulting.

Basic prerequisites

Three basic prerequisites are introduced in the next subsections, followed by a short example illustrating those aspects.

Scheduling and priority

The scheduling policy as well as the priority must be set by the application explicitly. There are two possibilities for this:

  1. Using sched_setscheduler() 
    This funcion needs to be called in the start routine of the pthread before calculating RT specific stuff.
  2. Using pthread attributes 
    The functions  pthread_attr_setschedpolicy() and  pthread_attr_setschedparam()offer the interfaces to set policy and priority. Furthermore scheduler inheritance needs to be set properly to PTHREAD_EXPLICIT_SCHED by using  pthread_attr_setinheritsched(). This forces the new thread to use the policy and priority specified by the pthread attributes and not to use the inherit scheduling of the thread which created the real-time thread.

Memory locking

See here

Stack for RT thread

See here

Example

/*                                                                  
 * POSIX Real Time Example
 * using a single pthread as RT thread
 */
 
#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h> #include <sys/mman.h>   void *thread_func(void *data) { /* Do RT specific stuff here */ return NULL; }   int main(int argc, char* argv[]) { struct sched_param param; pthread_attr_t attr; pthread_t thread; int ret;   /* Lock memory */ if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) { printf("mlockall failed: %m\n"); exit(-2); }   /* Initialize pthread attributes (default values) */ ret = pthread_attr_init(&attr); if (ret) { printf("init pthread attributes failed\n"); goto out; }   /* Set a specific stack size */ ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); if (ret) { printf("pthread setstacksize failed\n"); goto out; }   /* Set scheduler policy and priority of pthread */ ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO); if (ret) { printf("pthread setschedpolicy failed\n"); goto out; } param.sched_priority = 80; ret = pthread_attr_setschedparam(&attr, &param); if (ret) { printf("pthread setschedparam failed\n"); goto out; } /* Use scheduling parameters of attr */ ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); if (ret) { printf("pthread setinheritsched failed\n"); goto out; }   /* Create a pthread with specified attributes */ ret = pthread_create(&thread, &attr, thread_func, NULL); if (ret) { printf("create pthread failed\n"); goto out; }   /* Join the thread and wait until it is done */ ret = pthread_join(thread, NULL); if (ret) printf("join pthread failed: %m\n");   out: return ret; }

猜你喜欢

转载自www.cnblogs.com/wuhanlin/p/11782698.html