Как да стартирате C++, PortAudio приложение при стартиране на Angstrom Linux на BeagleBoard?

Имам приложение за команден ред, наречено xooky_nabox, което е програмирано с помощта на c++. Той чете кръпка puredata, обработва сигнали от аудио входния жак на бигълборд и извежда сигнали през аудио изходния жак.

Искам приложението да работи, когато 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, 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;
}

Опитвам се да го стартирам при стартиране

Опитах да стартирам и двете версии на програмата при стартиране, използвайки няколко метода. Резултатът винаги е един и същ. Когато бигълът стартира, мога да чуя извеждащ звук за част от секундата, след това звукът спира и се показва екранът за влизане (имам сериен терминал, свързан към платката и minicom, работещ на моя компютър). Най-странното за мен е, че процесът xooky_nabox всъщност продължава да работи след влизане, но няма изходен звук...

Ето какво опитах:

Добавяне на @reboot запис към crontab и стартиране на програмата с амперсанд в края (версия 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

И изпробва различни версии на стартиращия скрипт: start-stop-daemon с версия 1, извикване на програмата директно с амперсанд в края (версия 1), извикване на програмата директно без амперсанд в края (версия 2).

Освен това, ако стартирам програмата ръчно от серийния терминал или от ssh сесия (usb мрежа); и след това стартирам отгоре, програмата ще работи добре за няколко секунди, консумирайки около 15% процесор. След това ще спре да извежда звук и консумацията на процесора ще нарасне до около 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

Някой има ли някакви идеи как да се отстранят грешки? Предложения как да стартирам програмата си при стартиране?


person Rafael Vega    schedule 12.06.2011    source източник


Отговори (3)


Във версия 2 мисля, че трябва да opendup2) /dev/null до STDIN/STDOUT/STDERR. Самото затваряне на дръжката би причинило проблем.

нещо като това:

int fd = open("/dev/null", O_RDWR);
dup2( fd, STDOUT_FILENO );

(Нямам представа какво правят start-stop-daemon. Не мога да помогна с версия 1, съжалявам)

person J-16 SDiZ    schedule 13.06.2011

Има C функция за създаване на демон

#include <unistd.h>

int daemon(int nochdir, int noclose);

Повече информация може да се намери в man страниците за daemon(3) Може би ще помогне.

И ако искате да стартирате своя демон, когато стартирате Linux, трябва да разберете коя init версия използвате във вашата дистрибуция, но обикновено можете просто да добавите команда за изпълнение на вашия демон към /etc/init.d/rc (но изглежда не е толкова добра идея). Този файл се изпълнява от init, когато Linux стартира.

person Mikhail Boiko    schedule 24.06.2011

В крайна сметка се отказах от PortAudio и внедрих JACK клиент, който управлява свой собствен сървър, така че този проблем вече не беше от значение за мен.

person Rafael Vega    schedule 07.01.2012