内核sem、wait_queue_head_t、timer和kernel_thread使用驱动范例

浅析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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值