浅析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
本文介绍了一个基于Linux的定时器驱动实例,详细展示了如何利用sem、wait_queue_head_t等机制实现定时器的功能,并通过kernel_thread启动后台线程进行周期性的操作。

被折叠的 条评论
为什么被折叠?



