创建后台程序(应用)



Unix和其他多任务计算机操作系统中,后台程序是指,作为后台进程运行的计算机,而不是由交互用户直接控制。

后台程序概念的主要好处是,后台程序可以直接启动,而不需要将其发送到精确的用户或者shell的后台(然而,这不适用于Nuttx),其状态可以在运行的时候,通过shell查询。也可以终止。

Step 1: 创建一个小的标准应用

根据 FirstOnboard Application Tutorial (Hello Sky)教程(见PX4源码开发人员文档(二)),这是一个基本程序(简化):

[cpp] view plain copy print ?
  1. ..  
  2. __EXPORT int px4_daemon_app_main(int argc, char *argv[]);  
  3. ..  
  4. int px4_daemon_app_main(int argc, char *argv[])  
  5. {  
  6.     while (true) {  
  7.         warnx("Hello Daemon!\n");  
  8.         sleep(1);  
  9.     }  
  10.     return 0;  
  11. }  

这个应用的问题非常明显,如果不使用&启动,将会阻塞shellNuttx,并不如此,并且会出于small footprint和可靠性的原因,支持CTRL-Z / fg / bg)。为了回避这个问题,下面部分将应用转换为一个后台程序。


Step 2: 创建后台进程管理函数

主函数由后台进程管理函数替代,旧的主函数的内容现在位于后台任务/进程中

[cpp] view plain copy print ?
  1. #include <systemlib/systemlib.h>  
  2.    
  3. ..  
  4. __EXPORT int px4_daemon_app_main(int argc, char *argv[]);  
  5. ..  
  6. int mavlink_thread_main(int argc, char *argv[]);  
  7. ..  
  8. int mavlink_thread_main(int argc, char *argv[])  
  9. {  
  10.     while (true) {  
  11.         warnx("Hello Daemon!\n");  
  12.         sleep(1);  
  13.         if (thread_should_exit) break;  
  14.     }  
  15.    
  16.     return 0;  
  17. }  
  18. ..  
  19. int px4_daemon_app_main(int argc, char *argv[])  
  20. {  
  21.     if (argc < 1)  
  22.         usage("missing command");  
  23.    
  24.     if (!strcmp(argv[1], "start")) {  
  25.    
  26.         if (thread_running) {  
  27.             warnx("daemon already running\n");  
  28.             /* this is not an error */  
  29.             exit(0);  
  30.         }  
  31.    
  32.         thread_should_exit = false;  
  33.         daemon_task = task_spawn_cmd("daemon",  
  34.                          SCHED_RR,  
  35.                          SCHED_PRIORITY_DEFAULT,  
  36.                          4096,  
  37.                          px4_daemon_thread_main,  
  38.                          (argv) ? (const char **)&argv[2] : (const char **)NULL);  
  39.         thread_running = true;  
  40.         exit(0);  
  41.     }  
  42.    
  43.     usage("unrecognized command");  
  44.     exit(1);  
  45. }  

这将会启动一个新的任务,具有4096字节的堆栈,并传递非后台程序的具体指令行选项到后台主函数。典型的调用如下所示:

[plain] view plain copy print ?
  1. px4_daemon_app start  

上面的代码没有报告状态,并且没有对多次调用后台进程进行保护。

Step 3: 添加停止/状态指令以及安全保护

具有合适的启动/停止/状态建立和附加安全保护的完整px4_daemon_app代码如下:

[cpp] view plain copy print ?
  1. /** 
  2.  * @file px4_daemon_app.c 
  3.  * daemon application example for PX4 autopilot 
  4.  * 
  5.  * @author Example User <[email protected]> 
  6.  */  
  7.    
  8. #include <stdio.h>  
  9. #include <stdlib.h>  
  10. #include <string.h>  
  11. #include <unistd.h>  
  12.    
  13. #include <px4_config.h>  
  14. #include <nuttx/sched.h>  
  15.    
  16. #include <systemlib/systemlib.h>  
  17. #include <systemlib/err.h>  
  18.    
  19. static bool thread_should_exit = false;     /**< daemon exit flag */  
  20. static bool thread_running = false;     /**< daemon status flag */  
  21. static int daemon_task;             /**< Handle of daemon task / thread */  
  22.    
  23. /** 
  24.  * daemon management function. 
  25.  */  
  26. __EXPORT int px4_daemon_app_main(int argc, char *argv[]);  
  27.    
  28. /** 
  29.  * Mainloop of daemon. 
  30.  */  
  31. int px4_daemon_thread_main(int argc, char *argv[]);  
  32.    
  33. /** 
  34.  * Print the correct usage. 
  35.  */  
  36. static void usage(const char *reason);  
  37.    
  38. static void  
  39. usage(const char *reason)  
  40. {  
  41.     if (reason) {  
  42.         warnx("%s\n", reason);  
  43.     }  
  44.    
  45.     warnx("usage: daemon {start|stop|status} [-p <additional params>]\n\n");  
  46. }  
  47.    
  48. /** 
  49.  * The daemon app only briefly exists to start 
  50.  * the background job. The stack size assigned in the 
  51.  * Makefile does only apply to this management task. 
  52.  * 
  53.  * The actual stack size should be set in the call 
  54.  * to task_create(). 
  55.  */  
  56. int px4_daemon_app_main(int argc, char *argv[])  
  57. {  
  58.     if (argc < 2) {  
  59.         usage("missing command");  
  60.         return 1;  
  61.     }  
  62.    
  63.     if (!strcmp(argv[1], "start")) {  
  64.    
  65.         if (thread_running) {  
  66.             warnx("daemon already running\n");  
  67.             /* this is not an error */  
  68.             return 0;  
  69.         }  
  70.    
  71.         thread_should_exit = false;  
  72.         daemon_task = px4_task_spawn_cmd("daemon",  
  73.                          SCHED_DEFAULT,  
  74.                          SCHED_PRIORITY_DEFAULT,  
  75.                          2000,  
  76.                          px4_daemon_thread_main,  
  77.                          (argv) ? (char *const *)&argv[2] : (char *const *)NULL);  
  78.         return 0;  
  79.     }  
  80.    
  81.     if (!strcmp(argv[1], "stop")) {  
  82.         thread_should_exit = true;  
  83.         return 0;  
  84.     }  
  85.    
  86.     if (!strcmp(argv[1], "status")) {  
  87.         if (thread_running) {  
  88.             warnx("\trunning\n");  
  89.    
  90.         } else {  
  91.             warnx("\tnot started\n");  
  92.         }  
  93.    
  94.         return 0;  
  95.     }  
  96.    
  97.     usage("unrecognized command");  
  98.     return 1;  
  99. }  
  100.    
  101. int px4_daemon_thread_main(int argc, char *argv[])  
  102. {  
  103.    
  104.     warnx("[daemon] starting\n");  
  105.    
  106.     thread_running = true;  
  107.    
  108.     while (!thread_should_exit) {  
  109.         warnx("Hello daemon!\n");  
  110.         sleep(10);  
  111.     }  
  112.    
  113.     warnx("[daemon] exiting.\n");  
  114.    
  115.     thread_running = false;  
  116.    
  117.     return 0;  
  118. }  

代码测试将会产生如下的输出:

[plain] view plain copy print ?
  1. nsh> px4_daemon_app start  
  2. [daemon] starting  
  3. Hello Daemon!  

为了使用这一APP,只需在Firmware/makefiles/config_px4fmu_default.mk中,取消对这一示例部分的注释。



你可能感兴趣的:(创建后台程序(应用))