《编写LXRT(RTAI-LXRT)用户空间程序》由会员分享,可在线阅读,更多相关《编写LXRT(RTAI-LXRT)用户空间程序(8页珍藏版)》请在金锄头文库上搜索。
1、编写LXRT(RTAILXRT)用户空间程序Asad Chan 2011-06-28 此文档仅为那些刚涉猎RTAI Linux的爱好者编写。在用户空间下编写RTAILXRT程序并不是一件困难的事,可以参考DIAPM RTAI Programming Guide 1.0和How to port your C+ GNU/Linux application to RTAI/LXRT。而这两个文档却没有一个完整在用户空间能执行的例子,所以往往会造成看了遇到问题不知问题出在哪里。往往有的程序编写好了,也编译好了,在控制台下执行却出现了segmentation fault字样。 RTAI Linux 调度
2、器(请参考RTAI 3.3 User Manual rev0.2) RTAI分别在内核空间和用户空间提供了两个对等的任务调度器,一个为rtai_sched,一个为rtai_lxrt,这两个调度器主要是他们所能调度的可调度任务有所差异,而这两个调度器都能调度用户空间和内核空间的任务。rtai_sched能调度Linux下的各种任务,例如process,thread,kthread,而同时它还能调度RTAI 内核空间任务(请区分Linux内核和 RTAI 内核)。而rtai_lxrt仅能调度process,thread,kthread,却不能调度RTAI内核空间任务。 此文档仅介绍在用户空间执行的
3、实时性任务,而要使用这两个调度器,需将rtai_hal.ko,rtai_sched.ko,rtai_lxrt.ko三个模块加载进Linux内核,因为只有将这些模块加载进内核才能使这两个调度器运行起来并且能为实时性进程线程提供调度服务。也即在用户空间编写的实时性进程任务需要上述两个调度器中的一个提供调度服务才能正常运行。 现在开始吧! 1、建立main.c文件内容如下:#include #include #include #include static int end = 1;void endHandler(int sig) /信号处理函数end = 0; /使静态变量为0,这将是主函数的死循环
4、被breakint main(void) RT_TASK *task = 0; /定义实时任务指针,用于指向被创建的实时性任务int period = 0; /定义周期变量,用于存储定时器的周期signal(SIGKILL,endHandler); /连接几个主要关闭信号的信号处理函数signal(SIGTERM,endHandler); /包括KILL也即杀死进程信号,TERM关闭信号signal(SIGALRM,endHandler); /这些信号被收到时将会break主程序的循环if(!(task=rt_task_init_schmod(nam2num(TEST),0,0,0,SCHED
5、_FIFO,0x0f) /初始化本进程 /为实时性任务printf(Cant initial the taskn);exit(1);mlockall(MCL_CURRENT|MCL_FUTURE); /锁定本进程内存,防止本进程的内存页被换出 /导致的实时性被破坏period = start_rt_timer(nano2count(10000); /启动定时器,设置其定时周期/频率, /根据定时器是否是oneshotrt_make_hard_real_time(); /使本任务为硬(hard)实时性任务rt_task_make_periodic(task,rt_get_time()+perio
6、d*10,period*100); /设置本任务的周期while(end) /如果end为1则一直执行,end0,则说明接收到了kill/term/alrm三个信号 /中的一个,证明此进程被用户终止或alrm,则break此循环,结束此任务 printf(Hello World!n); /打印字符,注意,此为syscall,会导致任务进入非实时性 /状态,当此调用结束时将会重新返回到实时性状态 /* 在实际应用中如果你的任务是周期性执行的,请在此处填写需要执行的周期性过程。 如果你的任务是需要等待某个事件、者信号量或者某个消息的到来,请你建立相应 的事件、信号量、消息邮箱,并在此处等待相应的量
7、,相应的量到来时执行你需要的 操作。 */ rt_task_wait_period(); /使当前任务进入休眠,知道下一次执行周期到达被唤醒, /如果execution time = deadline则此函数不会使 /任务进入休眠状态rt_make_soft_real_time(); /是任务进入软实时状态stop_rt_timer(); /停止定时器rt_task_delete(task); /删除实时性任务,此时控制权将交回Linuxprintf(End of the Application!n);return 0; /返回0值 2、建立Makefile文件在Makefile文件内如下所写
8、:CC = gcc CFLAGS = -I/usr/realtime/include -oDFLAGS = -L/usr/realtime/lib -llxrt -lpthreadTARGET = mainSOURCE = main.call:$(CC) $(SOURCE) $(CFLAGS) $(TARGET) $(DFLAGS)clean:rm main注释: CFLAGS宏用于设置编译选项,可以看到“-I/usr/realtime/include”这项,此项用于设置包含rtai_lxrt.h的路径(path),其原因在于此路径不是Linux的标准头文件路径,因此需要手动在编译选项里指定其
9、路径,其选项为“-I”。“-o”选项用于告诉编译器编译成可执行文件。 DFLAGS宏用于设置连接选项,可以看到“-L/usr/realtime/lib”这项,这项用于指定静态库“liblxrt.a”的路径,因为此文件不在Linux的标准库路径下,需要手动设置其路径,其选项为“-L”。需要手动指定其静态库,可见“-llxrt” “-lpthread”两项,其中“-llxrt”实为liblxrt.a的缩写,此实为GNU连接器的使用规则,由此可知“-lpthread”即为libpthread.a的缩写。 “$()”符号用于对定义的宏进行解析,例如“$(CC)”在上面的例子中等价为“gcc”,“$(S
10、OURCE)”等价为“main.c”,其他各项亦按此种形式解析。 3、编译main.c文件 假设你的main.c、Makefile两个文件放在绝对路径/usr/root/workspace/main目录里,那么在控制台下进入到此目录,执行以下命令即可: make 注:“”为回车的意思。 此时控制台上会显示“gcc main.c -I/usr/realtime/include -o main -L/usr/realtime/lib -llxrt -lpthread”,同时在main目录下会生成可执行文件main。 4、执行main 此时,在上面步骤下在控制台下执行以下命令: ./main 此时,
11、会返回一个错误,类似于“cant open file liblxrt.so.1 .”之类的字样,其原因是文件liblxrt.so.1并不是在Linux系统设定的静态库路径下,那么要解决这个问题需要将在第2步中设定路径“/usr/realtime/lib”加入到Linux系统能寻找的静态库的路径中,此可以通过以下命令设定: ldconfig /usr/realtime/lib 注:ldconfig即为设置静态库查找路径命令,其参数即为你需要设置的静态库路径。 此时,你再执行: ./main 你又发现出问题了,其表现为控制台返回“segmentation fault”,也即为段错误。还记得在“RT
12、AI Linux 调度器”一节中曾提到过rtai_hal.ko, rtai_sched.ko, rtai_lxrt.ko三个模块,根据该小节中的解释,需要运行main程序,必须要将这三个模块加载到内核空间,以使其提供调度任务服务功能。首先要切换到目录/usr/realtime/modules下,也即如下命令: cd /usr/realtime/modules 继续执行以下命令: insmod rtai_hal.ko insmod rtai_sched.ko insmod rtai_lxrt.ko 此时,再重新执行以下命令: ./main 此时,控制台上将会不断打印“Hello World!”。 此时可以通过按下“Ctrl + C”来终止程序,而更建议在任务管理器下将此进程杀死,因为程序里实现了信号kill的处理函数。 疑惑还是存在 疑惑的存在主要是在main函数里的各个步骤还是难以让人理解。例如singal函数的调用是一件比较难以明白的处理,里面连接了kill信号,在kill的处理句柄里可以看到它将end赋0,而end为0将会导致main函数里的循环结束。而在Linux系统里kill信号是有默认的处理句柄的,那么我们为什么不用它的默认处理句柄呢?它同样可以使应用程序退出并