Как добавить peridic обратного вызова таймера в модуль ядра Linux
Я работаю над модулем ядра Linux, который регистрирует обратный вызов для прерываний, поступающих с пользовательской платы, и помещает полученные данные в очередь за интерфейсом устройства char для обработки приложением. Этот модуль должен постоянно отслеживать и измерять прерывания и данные, поступающие с платы, даже если прерывания не поступают с платы, поэтому у него есть еще один обратный вызов, который срабатывает в соответствии со временем.
Текущая реализация использует прерывание RTC в качестве константы источник таймера. Я отключаю драйверы ядра RTC (CONFIG_RTC_DRV_CMOS
) и запрашиваю IRQ 8 и подключаю обратный вызов таймера в качестве обработчика прерываний RTC. Прерывания генерируются каждую секунду от чипа RTC.
rtc-cmos
или модуль платы может быть загружен сразу (и, очевидно, мы выбрали модуль платы).
Целевая архитектура - i386 PC.
Я не разработчик ядра и поэтому не имею большого картинка на разработке модуля ядра, но я пытаюсь найти свой путь, и это самое близкое к решению, которое приходит мне на ум:
- как-то разделить IRQ 8 между обоими модулями (может быть, как
request_irq(8, rtc_handler, IRQF_SHARED, rtc_handler)
?) или обработчики IRQ chainload. - поиск другого способа подключить обработчик из модуля ядра к прерыванию RTC, а не регистрироваться для IRQ 8.
- поиск другого источника событий 1-секундного таймера, который может быть использован из модуля ядра, возможно, существует стандарт ядро API для этого, я не знаю.
2 ответа:
Таймер высокого разрешения ядра Linux
hrtimer
- это опция. http://lwn.net/Articles/167897/Вот что я делаю:
#include <linux/interrupt.h> #include <linux/hrtimer.h> #include <linux/sched.h> static struct hrtimer htimer; static ktime_t kt_periode; static void timer_init(void) { kt_periode = ktime_set(0, 104167); //seconds,nanoseconds hrtimer_init (& htimer, CLOCK_REALTIME, HRTIMER_MODE_REL); htimer.function = timer_function; hrtimer_start(& htimer, kt_periode, HRTIMER_MODE_REL); } static void timer_cleanup(void) { hrtimer_cancel(& htimer); } static enum hrtimer_restart timer_function(struct hrtimer * timer) { // @Do your work here. hrtimer_forward_now(timer, kt_periode); return HRTIMER_RESTART; }