下一页 上一页 目录

4. 编写 RTLinux 程序

4.1 模块编写简介

那么什么是模块?Linux 模块不过是一个目标文件,通常使用 gcc 的 -c 标志参数创建。模块本身是通过编译一个普通的 C 语言文件创建的,该文件没有 main() 函数。相反,会有一对 init_module/cleanup_module 函数

通常,init_module() 要么向内核注册一个处理程序,要么用自己的代码替换内核函数之一(通常是执行某些操作然后调用原始函数的代码)。cleanup_module() 函数的作用是撤销 init_module() 所做的任何操作,以便可以安全地卸载模块。

例如,如果您编写了一个名为 module.c 的 C 文件(其中 init_module() 和 cleanup_module() 替换了 main() 函数),则可以通过键入以下命令将代码转换为模块:

        $ gcc -c {SOME-FLAGS} my_module.c

此命令创建一个名为 module.o 的模块文件,现在可以使用 'insmod' 命令将其插入内核

        $ insmod module.o

类似地,要移除模块,可以使用 'rmmod' 命令

        $ rmmod module

4.2 创建 RTLinux 线程

一个实时应用程序通常由几个“线程”组成。线程是共享公共地址空间的轻量级进程。在 RTLinux 中,所有线程共享 Linux 内核地址空间。使用线程的优点是,与上下文切换相比,线程之间的切换非常廉价。我们可以通过使用不同的函数来完全控制线程的执行,这将在后面的示例中展示。

4.3 示例程序

理解线程工作原理的最佳方法是跟踪一个实时程序。例如,下面显示的程序将每秒执行一次,并且在每次迭代期间它将打印 'Hello World'。

程序代码 (文件 - hello.c)

#include <rtl.h>
#include <time.h>
#include <pthread.h>

pthread_t thread;

void * thread_code(void)
{
        pthread_make_periodic_np(pthread_self(), gethrtime(), 1000000000);

        while (1)
        {
                pthread_wait_np ();
                rtl_printf("Hello World\n");
        }

        return 0;
}

int init_module(void) 
{
   return pthread_create(&thread, NULL, thread_code, NULL);
}

void cleanup_module(void) 
{
   pthread_delete_np(thread);
}

所以,让我们从 init_module() 开始。init_module() 调用 pthread_create()。这是为了创建一个与调用线程并发执行的新线程。此函数只能从 Linux 内核线程(即,使用 init_module())调用。

        int  pthread_create(pthread_t  * thread,
                            pthread_attr_t * attr,
                            void * (*thread_code)(void *),
                            void * arg);

新创建的线程类型为 pthread_t,在头文件 pthread.h 中定义。此线程执行函数 thread_code(),并将 arg 作为其参数传递给它。attr 参数指定要应用于新线程的线程属性。如果 attr 为 NULL,则使用默认属性。

因此,这里调用 thread_code() 时没有参数。thread_code 有三个组成部分 - 初始化、运行时和终止。

在初始化阶段,是调用 pthread_make_periodic_np()。

        int pthread_make_periodic_np(pthread_t thread, 
                                     hrtime_t start_time, 
                                     hrtime_t period);

pthread_make_periodic_np 将 thread 标记为准备执行。线程将在 start_time 时开始执行,并以 period 指定的间隔(以纳秒为单位)运行。

gethrtime 返回自系统启动以来以纳秒为单位的时间。

       hrtime_t gethrtime(void);

此时间永远不会重置或调整。gethrtime 始终提供单调递增的值。hrtime_t 是一个 64 位有符号整数。

通过调用函数 pthread_make_periodic_np(),线程告诉调度器以 1 Hz 的频率定期执行此线程。这标志着线程初始化部分的结束。

while() 循环以调用函数 pthread_wait_np() 开始,该函数挂起当前正在运行的实时线程的执行,直到下一个周期的开始。该线程先前已使用 pthread_make_periodic_np 标记为执行。一旦再次调用该线程,它将执行 while 循环内的其余内容,直到它遇到另一个对 pthread_wait_np() 的调用。

因为我们没有包含任何退出循环的方法,所以此线程将以 1Hz 的速率永远执行下去。停止程序的唯一方法是通过使用 rmmod 命令从内核中移除它。这将调用 cleanup_module(),后者调用 pthread_delete_np() 来取消线程并释放其资源。


下一页 上一页 目录