Функции C, вызываемые как потоки - программа пользователя Linux - PullRequest
3 голосов
/ 14 мая 2010

Я пишу демон Linux на C, который получает значения из АЦП через интерфейс SPI (ioctl). SPI (spidev - userland) кажется немного нестабильным и замораживает демона в случайные моменты времени.

Мне нужно лучше контролировать вызовы функций, получающих значения, и я думал о том, чтобы сделать его потоком, который я мог бы дождаться, чтобы закончить и получить возвращаемое значение, и, если время ожидания истекло, предположим, что оно заморозить и убить его без этой новой нити, уничтожающей самого демона. Тогда я мог бы применить меры, такие как сброс АЦП перед перезапуском. Это возможно?

Псевдо-пример того, чего я хочу достичь:

(функция int get_adc_value (int adc_channel, значение с плавающей точкой *) )

  1. pid = thread (get_adc_value (1, & value); // делает поток вызывающим функцию
  2. wait_until_finish (pid, timeout); // ждет окончания функции / timeout
  3. если (тайм-аут) уничтожить pid, начать заново // если поток не возвращается в течение заданного времени, уничтожить его (он заморожен)
  4. иначе, если возвращаемое значение нормальное, продолжить //, если успешно, обработать возвращаемое значение переменной и продолжить

Спасибо за любой вклад по этому вопросу, примеры высоко ценятся!

Ответы [ 4 ]

2 голосов
/ 14 мая 2010

Я бы попытался использовать библиотеку pthreads . Я использовал его для некоторых из моих c проектов с большим успехом, и он дает вам довольно хороший контроль над тем, что и когда выполняется.

Очень хороший учебник можно найти здесь: http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

1 голос
/ 14 мая 2010

В glib также есть способ проверить потоки, используя GCond (ищите это в справке glib).

В резюме вы должны периодически устанавливать GCond в дочернем потоке и проверять его в основном потоке с помощью g_cond_timed_wait. То же самое с бойком или птхедом.

Вот пример с pthread: http://koders.com/c/fidA03D565734AE2AD9F5B42AFC740B9C17D75A33E3.aspx?s=%22pthread_cond_timedwait%22#L46

0 голосов
/ 15 мая 2010

Что-то очень интересное случается с потоком, когда он выполняет ioctl (), он входит в очень особый вид сна, известный как дисковый сон , где он не может быть прерван или прерван до тех пор, пока не завершится вызов. Это сделано специально и предотвращает гниение ядра изнутри.

Если ваш демон застревает в ioctl(), вполне возможно, что он может оставаться таким всегда (по крайней мере, пока АЦП не будет переустановлен).

Я бы посоветовал сбросить что-то, например, файл с отметкой времени до , чтобы вызвать ioctl() на известном ошибочном интерфейсе. Если ваш поток не отменяет связь с этим файлом за xx секунд, что-то еще нужно перезапустить АЦП.

Я также согласен с использованием pthreads, если вам нужен пример кода, просто обновите свой вопрос.

0 голосов
/ 14 мая 2010

Я бы рекомендовал другой подход.

Напишите программу, которая берет сэмплы и записывает их в стандартный вывод. Ему просто нужно иметь alarm(TIMEOUT); перед каждым сбором образцов, и если он зависнет, программа автоматически завершится.

Напишите другую программу, которая запускает эту первую программу. Если он выходит, он запускает его снова. Это выглядит примерно так:

main(){for(;;){system("sampler");sleep(1);}}

Затем в другой программе используйте FILE*fp=popen("supervise_sampler","r"); и прочитайте примеры из fp. Еще лучше: пусть программа просто прочитает примеры из stdin и настаивает на том, чтобы пользователи запускали вашу программу следующим образом:

(while true;do sampler;sleep 1; done)|program

Разделение задачи таким образом упрощает разработку и тестирование, например, вы можете собирать образцы и сохранять их в файл, а затем запускать программу с этим файлом:

sampler > data
program < data

Затем, внося изменения в программу, вы можете просто снова и снова запускать ее для одних и тех же данных.

Включение регистрации данных также тривиально, поэтому, если вы обнаружите серьезную проблему, вы можете снова запустить все свои данные через программу, чтобы найти ошибки.

...