问题描述
|
我有一个名为xooky_naBox的命令行应用程序,该应用程序是使用c ++编程的。它读取puredata补丁,处理来自Beagleboard音频输入插孔的信号,并通过音频输出插孔输出信号。
我希望应用程序在beagleoard启动后运行并保持运行状态,直到主板关闭。没有GUI,没有键盘或显示器,只是音频输入和输出插孔。
如果我手动运行该应用程序,则一切正常:
xooky_naBox -audioindev 1 -audiooutdev 1 /var/xooky/patch.pd
如果我在后台运行它,它也可以正常运行:
xooky_naBox -audioindev 1 -audiooutdev 1 /var/xooky/patch.pd &
现在,让我展示该程序的两个版本的代码布局(完整的内容位于https://github.com/rvega/XookyNaBox):
版本1,主线程保持活动状态:
void sighandler(int signum){
time_t rawtime;
time(&rawtime);
std::ofstream myfile;
myfile.open (\"log.txt\",std::ios::app);
myfile << ctime(&rawtime) << \" Caught signal:\" << signum << \" \" << strsignal(signum) << \"\\n\";
myfile.close();
if(signum == 15 || signum == 2){
exit(0);
}
}
int main (int argc,char *argv[]) {
// Subscribe to all system signals for debugging purposes.
for(int i=0; i<64; i++){
signal(i,sighandler);
}
// Sanity checks,error and help messages,etc.
parseParameters(argc,argv);
//Start Signal processing and Audio
initZenGarden();
initAudioIO();
// Keep the program alive.
while(1){
sleep(10);
}
// This is obvIoUsly never reached,so far no problems with that...
stopAudioIO();
stopZengarden();
return 0;
}
static int paCallback( const void *inputBuffer,void *outputBuffer,unsigned long framesPerBuffer,const PaStreamCallbackTimeInfo* timeInfo,PaStreamCallbackFlags statusFlags,void *userData ){
// This is called by PortAudio when the output buffer is about to run dry.
}
版本2,执行是分叉的,并且与启动它的终端分离:
void go_daemon(){
// Run the program as a daemon.
pid_t pid,sid;
pid = fork(); // Fork off the parent process
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS); // If child process started ok,exit the parent process
}
umask(0); // Change file mode mask
sid = setsid(); // Create a new session ID for the child process
if (sid < 0) {
// Todo: Log failure
exit(EXIT_FAILURE);
}
if((chdir(\"/\")) < 0){ //Change the working directory to \"/\"
//Todo: Log failre
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
int main (int argc,char *argv[]) {
go_daemon();
// Subscribe to all system signals for debugging purposes.
for(int i=0; i<64; i++){
signal(i,so far no problems with that...
stopAudioIO();
stopZengarden();
return 0;
}
尝试在启动时运行它
我尝试使用几种方法在启动时运行程序的两个版本。结果总是一样的。当小猎犬启动时,我可以听到声音发声输出一秒钟的时间,然后声音停止,并显示登录屏幕(我在开发板上连接了一个串行终端,并且在我的计算机上运行了minicom)。对我来说最奇怪的是,登录后xooky_naBox进程实际上一直在运行,但是没有声音输出...
这是我尝试过的:
在crontab中添加一个@reboot条目,并使用后跟符号(程序的版本1)启动该程序:
@reboot xooky_naBox <params> &
向crontab(版本1)添加了一个start-stop-daemon:
@reboot start-stop-daemon -S -b --user daemon -n xooky_naBox -a /usr/bin/xooky_naBox -- <params>
在/etc/init.d/xooky中创建了一个脚本并执行了
$chmod +x xooky
$update-rc.d xooky defaults
并尝试了不同版本的启动脚本:带有版本1的start-stop-daemon,直接在末尾的&符(版本1)下调用该程序,在没有尾部的&符(版本2)下直接调用该程序。
另外,如果我从串行终端或ssh会话(usb联网)手动运行程序;然后运行top,该程序将在几秒钟内正常运行,消耗约15%的cpu。然后它将停止输出声音,并且它的cpu消耗将上升到30%左右。在这种情况下,我的log.txt文件没有显示操作系统发送的信号。
当程序的版本2在启动时运行时,日志将显示类似以下内容:
Mon Jun 6 02:44:49 2011 Caught signal:18 Continued
Mon Jun 6 02:44:49 2011 Caught signal:15 Terminated
有谁对如何调试有任何想法吗?有关如何在启动时启动程序的建议?
解决方法
在版本2中,
我认为您应该将
open
(和dup2
)/dev/null
改成STDIN
/STDOUT
/STDERR
。仅关闭手柄会引起问题。
像这样的东西:
int fd = open(\"/dev/null\",O_RDWR);
dup2( fd,STDOUT_FILENO );
(我不知道start-stop-daemon做什么。无法帮助版本1,抱歉)
, 有C函数创建守护程序
#include <unistd.h>
int daemon(int nochdir,int noclose);
有关更多信息,请参见man16的手册页。
也许会有所帮助。
而且,如果您想在Linux启动时启动守护程序,则应该找出发行版中使用的是哪个ѭ17but版本,但是通常情况下,您只需添加命令即可将您的守护程序执行到/etc/init.d/rc
(但这似乎不太好)理念)。 linux启动时,此文件由ѭ17执行。
, 我最终放弃了PortAudio并实现了一个JACK客户端来运行它自己的服务器,所以这个问题对我来说不再重要了。