那么什么是模块?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
一个实时应用程序通常由几个“线程”组成。线程是共享公共地址空间的轻量级进程。在 RTLinux 中,所有线程共享 Linux 内核地址空间。使用线程的优点是,与上下文切换相比,线程之间的切换非常廉价。我们可以通过使用不同的函数来完全控制线程的执行,这将在后面的示例中展示。
理解线程工作原理的最佳方法是跟踪一个实时程序。例如,下面显示的程序将每秒执行一次,并且在每次迭代期间它将打印 '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() 来取消线程并释放其资源。