浅析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】.
原文地址:http://blog.chinaunix.net/u1/38994/showart_1130557.html
附件为:gliethttp_timer.tar.bz2