如何在 BeagleBoard 上的 Angstrom Linux 上启动时运行 C++ PortAudio 应用程序?
我有一个名为 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,执行分叉并分离从启动的终端it:
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, 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;
}
尝试在启动时运行它
我尝试使用几种方法在启动时运行该程序的两个版本。结果总是一样的。当小猎犬启动时,我可以听到声音输出一小会儿,然后声音停止并显示登录屏幕(我的主板上连接了一个串行终端,我的计算机上运行着微型计算机)。对我来说最奇怪的事情是 xooky_nabox 进程实际上在登录后保持运行,但没有声音输出...
这是我尝试过的:
向 crontab 添加 @reboot 条目并使用尾随的 & 符号启动程序(版本 1程序的):
@reboot xooky_nabox <params> &
向 crontab 添加了一个启动-停止-守护进程(版本 1):
@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
有人对如何调试它有任何想法吗?关于如何在启动时启动我的程序的建议?
I have a command-line application called xooky_nabox that was programmed using c++. It reads a puredata patch, processes signals from the audio in jack of a beagleboard and outputs signals through the audio out jack.
I want the application to run wen the beagleoard starts up and stay running until the board is shut down. There is no GUI and no keyboard or monitor attached to it, just the audio in and out jacks.
If I run the application manually everything works fine:
xooky_nabox -audioindev 1 -audiooutdev 1 /var/xooky/patch.pd
And it also runs fine if I run it in the background:
xooky_nabox -audioindev 1 -audiooutdev 1 /var/xooky/patch.pd &
Now, let me show the code layout of two versions of the program (The full thing is at https://github.com/rvega/XookyNabox):
Version 1, main thread is kept alive:
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.
}
Version 2, execution is forked and detached from the terminal that launched it:
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, 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;
}
Trying to run it at startup
I've tried running both versions of the program at startup using a few methods. The outcome is always the same. When the beagle starts up, I can hear sound beign output for a fraction of a second, the sound then stops and the login screen is presented (I have a serial terminal attached to the board and minicom running on my computer). The weirdest thing to me is that the xooky_nabox process is actually kept running after login but there is no sound output...
Here's what I've tried:
Adding a @reboot entry to crontab and launching the program with a trailing ampersand (version 1 of the program):
@reboot xooky_nabox <params> &
Added a start-stop-daemon to crontab (version 1):
@reboot start-stop-daemon -S -b --user daemon -n xooky_nabox -a /usr/bin/xooky_nabox -- <params>
Created a script at /etc/init.d/xooky and did
$chmod +x xooky
$update-rc.d xooky defaults
And tried different versions of the startup script: start-stop-daemon with version 1, calling the program directly with a trailing ampersand (version 1), calling the program directly with no trailing ampersand (version 2).
Also, if I run the program manually from the serial terminal or from a ssh session (usb networking); and then I run top, the program will run fine for a few seconds consuming around 15% cpu. It will then stop outputing sound, and it's cpu consumption will rise to around 30%. My log.txt file shows no signal sent to the program by the OS in this scenario.
When version 2 of the program is ran at startup, the log wil show something like:
Mon Jun 6 02:44:49 2011 Caught signal:18 Continued
Mon Jun 6 02:44:49 2011 Caught signal:15 Terminated
Does anyone have any ideas on how to debug this? Suggestions on how to launch my program at startup?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在版本 2 中,
我认为你应该
打开
(和dup2
)/dev/null
到STDIN
/STDOUT/<代码>STDERR。仅关闭手柄就会导致问题。
像这样的东西:(
我不知道启动停止守护进程做什么。无法帮助版本1,抱歉)
In version 2,
I think you should
open
(anddup2
)/dev/null
toSTDIN
/STDOUT
/STDERR
. Just closing the handle would cause problem.something like this:
(I have no idea what start-stop-daemon do. Can't help version 1, sorry)
有一个 C 函数可以创建守护进程
更多信息可以在
daemon(3)
的手册页中找到也许会有帮助。
如果你想在 Linux 启动时启动守护进程,你应该找出你的发行版中使用的是哪个
init
版本,但通常,你只需将执行守护进程的命令添加到/etc/init.d/rc
(但这似乎不是一个好主意)。当linux启动时,这个文件由init
执行。There is C function to create a daemon
More information can be found in man pages for
daemon(3)
Maybe it will help.
And if you want to launch you daemon when you linux start, you should find out which
init
version you are using in you distro, but usually, you can just add command to execute you daemon to/etc/init.d/rc
(but it seems to be no so good idea). This file is executed byinit
when linux is starting.我最终放弃了 PortAudio 并实现了一个运行它自己的服务器的 JACK 客户端,因此这个问题与我不再相关。
I ended up ditching PortAudio and implementing a JACK client which runs it's own server so this issue was not relevant for me anymore.