PX4源码开发人员文档(四)——创建后台程序(应用)

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

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

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

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

..
__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: 创建后台进程管理函数

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

#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字节的堆栈,并传递非后台程序的具体指令行选项到后台主函数。典型的调用如下所示:

px4_daemon_app start

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

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

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


/**
 * @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;
}

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

nsh> px4_daemon_app start
[daemon] starting
Hello Daemon!

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



版权声明:本文为博主[翻译]文章,未经博主允许可以转载,注明博客出处:[http://blog.youkuaiyun.com/lkk05]




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值