浅析linux内核中sem、wait_queue_head_t、timer和kernel_thread使用驱动范例
#include <linux/sched.h>
#define __TIMER_TEST_MOD1 1
#define __TIMER_TEST_MOD2 2
#define __TIMER_TEST_MOD3 3
#define __TIMER_TEST_MOD4 4
#define __TIMER_TEST_MOD5 5
#define __TIMER_TEST_MOD6 6
#define TIMER_TEST_MOD __TIMER_TEST_MOD6
static inline void restart_timer_delay(struct timer_list *timer, unsigned long msecs)
{
mod_timer(timer,jiffies + msecs_to_jiffies(msecs));
}
struct _sgliethttp_timer
{
wait_queue_head_t waitQ;
struct semaphore sem;
struct timer_list timer;
int timer_freq;
volatile int timer_counts;
volatile int thread_run,thread_quited;
};
static struct _sgliethttp_timer sgliethttp_timer, *gliethttp_timer;
static void timer_func(unsigned long data)
{
restart_timer_delay(&gliethttp_timer->timer, gliethttp_timer->timer_freq);
gliethttp_timer->timer_counts++;
#if (TIMER_TEST_MOD == __TIMER_TEST_MOD2)
up(&gliethttp_timer->sem);
#endif
#if ( (TIMER_TEST_MOD == __TIMER_TEST_MOD3) || \
(TIMER_TEST_MOD == __TIMER_TEST_MOD4) || \
(TIMER_TEST_MOD == __TIMER_TEST_MOD5) || \
(TIMER_TEST_MOD == __TIMER_TEST_MOD6) || 0\
)
wake_up(&gliethttp_timer->waitQ);
//对于wait_event_interruptible_timeout和wait_event_timeout来说,
//就是唤醒timer_thread,然后检查pre_timer_count != gliethttp_timer->timer_counts是否为真,
//如果为真,那么将退出wait_event_interruptible_timeout和wait_event_timeout.
#endif
}
static int timer_thread(void *data)
{
#if ( (TIMER_TEST_MOD == __TIMER_TEST_MOD1) || \
(TIMER_TEST_MOD == __TIMER_TEST_MOD3) || \
(TIMER_TEST_MOD == __TIMER_TEST_MOD4) || 0\
)
int pre_timer_count = gliethttp_timer->timer_counts;
#endif
while(gliethttp_timer->thread_run)
{
#if (TIMER_TEST_MOD == __TIMER_TEST_MOD1)
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);printk("M");
if(gliethttp_timer->timer_counts != pre_timer_count)
{
printk("L");
pre_timer_count = gliethttp_timer->timer_counts;
}
#endif
#if (TIMER_TEST_MOD == __TIMER_TEST_MOD2)
//down_interruptible(&gliethttp_timer->sem);
down(&gliethttp_timer->sem);
printk("L");
#endif
#if (TIMER_TEST_MOD == __TIMER_TEST_MOD3)
wait_event_timeout(gliethttp_timer->waitQ, pre_timer_count != gliethttp_timer->timer_counts, 5*HZ);
pre_timer_count++;
printk("L");
#endif
#if (TIMER_TEST_MOD == __TIMER_TEST_MOD4)
wait_event_interruptible_timeout(gliethttp_timer->waitQ, pre_timer_count != gliethttp_timer->timer_counts, 5*HZ);
pre_timer_count++;
printk("L");
#endif
#if ( (TIMER_TEST_MOD == __TIMER_TEST_MOD5) || (TIMER_TEST_MOD == __TIMER_TEST_MOD6) )
interruptible_sleep_on_timeout(&gliethttp_timer->waitQ, 5*HZ);
printk("L");
#endif
}
gliethttp_timer->thread_quited = 1;
return 0;
}
static int init_gliethttp_timer(void)
{
gliethttp_timer = &sgliethttp_timer;
init_waitqueue_head(&gliethttp_timer->waitQ);
init_MUTEX_LOCKED(&gliethttp_timer->sem);
//init_MUTEX(&gliethttp_timer->sem);
//sema_init(&gliethttp_timer->sem, 10);
gliethttp_timer->thread_run = 1;
gliethttp_timer->thread_quited = 0;
gliethttp_timer->timer_counts = -1;
gliethttp_timer->timer_freq = 100;
setup_timer(&gliethttp_timer->timer, timer_func, gliethttp_timer->timer_freq);
restart_timer_delay(&gliethttp_timer->timer, gliethttp_timer->timer_freq);
kernel_thread(timer_thread, NULL, 0);
printk(KERN_DEBUG"timer test start!\n");
printk(KERN_EMERG"timer test start!\n");
printk(KERN_ALERT"timer test start!\n");
printk(KERN_CRIT"timer test start!\n");
printk(KERN_ERR"timer test start!\n");
printk(KERN_WARNING"timer test start!\n");
printk(KERN_NOTICE"timer test start!\n");
printk(KERN_INFO"timer test start!\n");
//没咒念了,只能使用dmesg|tail来查看结果了
return 0;
}
static void cleanup_gliethttp_timer(void)
{
//del_timer(&timer);
del_timer_sync(&gliethttp_timer->timer);
#if (TIMER_TEST_MOD == __TIMER_TEST_MOD6)
{
gliethttp_timer->thread_run = 0;
wake_up(&gliethttp_timer->waitQ);
//如果在等待,那么唤醒timer_thread,让他去检测while(gliethttp_timer->thread_run)
while(gliethttp_timer->thread_quited == 0)
{
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
printk("Q");
}
}
#endif
printk(KERN_DEBUG"\nGoodbye, timer test\n");
}
module_init(init_gliethttp_timer);
module_exit(cleanup_gliethttp_timer)
====================================
Makefile中内容
obj-m:=gliethttp_timer.o
然后执行:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
即可编译生成出 gliethttp_timer.ko
然后insmod gliethttp_timer.ko 即可 【gliethttp.Leith】.
|