创建后台程序



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

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

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

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

  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. }  
..
__EXPORT int px4_daemon_app_main(int argc, char *argv[]);
..
int px4_daemon_app_main(int argc, char *argv[])
{
	while (true) {
		warnx("Hello Daemon!\n");
		sleep(1);
	}
	return 0;
}

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


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

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

  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. }  
#include <systemlib/systemlib.h>
 
..
__EXPORT int px4_daemon_app_main(int argc, char *argv[]);
..
int mavlink_thread_main(int argc, char *argv[]);
..
int mavlink_thread_main(int argc, char *argv[])
{
	while (true) {
		warnx("Hello Daemon!\n");
		sleep(1);
		if (thread_should_exit) break;
	}
 
	return 0;
}
..
int px4_daemon_app_main(int argc, char *argv[])
{
	if (argc < 1)
		usage("missing command");
 
	if (!strcmp(argv[1], "start")) {
 
		if (thread_running) {
			warnx("daemon already running\n");
			/* this is not an error */
			exit(0);
		}
 
		thread_should_exit = false;
		daemon_task = task_spawn_cmd("daemon",
					     SCHED_RR,
					     SCHED_PRIORITY_DEFAULT,
					     4096,
					     px4_daemon_thread_main,
					     (argv) ? (const char **)&argv[2] : (const char **)NULL);
		thread_running = true;
		exit(0);
	}
 
	usage("unrecognized command");
	exit(1);
}

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

  1. px4_daemon_app start  
px4_daemon_app start

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

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

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

  1. /** 
  2.  * @file px4_daemon_app.c 
  3.  * daemon application example for PX4 autopilot 
  4.  * 
  5.  * @author Example User <mail@example.com> 
  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. }  
/**
 * @file px4_daemon_app.c
 * daemon application example for PX4 autopilot
 *
 * @author Example User <mail@example.com>
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#include <px4_config.h>
#include <nuttx/sched.h>
 
#include <systemlib/systemlib.h>
#include <systemlib/err.h>
 
static bool thread_should_exit = false;		/**< daemon exit flag */
static bool thread_running = false;		/**< daemon status flag */
static int daemon_task;				/**< Handle of daemon task / thread */
 
/**
 * daemon management function.
 */
__EXPORT int px4_daemon_app_main(int argc, char *argv[]);
 
/**
 * Mainloop of daemon.
 */
int px4_daemon_thread_main(int argc, char *argv[]);
 
/**
 * Print the correct usage.
 */
static void usage(const char *reason);
 
static void
usage(const char *reason)
{
	if (reason) {
		warnx("%s\n", reason);
	}
 
	warnx("usage: daemon {start|stop|status} [-p <additional params>]\n\n");
}
 
/**
 * The daemon app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int px4_daemon_app_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}
 
	if (!strcmp(argv[1], "start")) {
 
		if (thread_running) {
			warnx("daemon already running\n");
			/* this is not an error */
			return 0;
		}
 
		thread_should_exit = false;
		daemon_task = px4_task_spawn_cmd("daemon",
						 SCHED_DEFAULT,
						 SCHED_PRIORITY_DEFAULT,
						 2000,
						 px4_daemon_thread_main,
						 (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
		return 0;
	}
 
	if (!strcmp(argv[1], "stop")) {
		thread_should_exit = true;
		return 0;
	}
 
	if (!strcmp(argv[1], "status")) {
		if (thread_running) {
			warnx("\trunning\n");
 
		} else {
			warnx("\tnot started\n");
		}
 
		return 0;
	}
 
	usage("unrecognized command");
	return 1;
}
 
int px4_daemon_thread_main(int argc, char *argv[])
{
 
	warnx("[daemon] starting\n");
 
	thread_running = true;
 
	while (!thread_should_exit) {
		warnx("Hello daemon!\n");
		sleep(10);
	}
 
	warnx("[daemon] exiting.\n");
 
	thread_running = false;
 
	return 0;
}

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

  1. nsh> px4_daemon_app start  
  2. [daemon] starting  
  3. Hello Daemon!  
nsh> px4_daemon_app start
[daemon] starting
Hello Daemon!

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值