2013-11-15 3 views
0

다음 코드에 문제가 있습니다. ioctl REGISTER를 호출 할 때마다 타이머가 시작되고 만료되면 작업 큐를 사용하여 작업을 예약하는 "update"를 호출합니다. doJob 메서드는 새 만료 타이머를 간단히 업데이트합니다.struct timer_list, 타이머가 중지되지 않습니다

ioctl UNREGISTER를 호출하면 타이머가 종료되지만 ... 업데이트를 계속 호출하므로 만료 날짜가 업데이트됩니다. ioctl UNREGISTER를 호출 한 후 타이머가 멈추지 않는 이유는 무엇입니까?

Callers must prevent restarting of the timer, otherwise this function is meaningless. 

, 핸들러가 종료 할 del_timer_sync() 대기,하지만 핸들러가 타이머를 다시 예약하는 경우, 다음 행복하게 다시 다음을 실행합니다 :

int time = 1; 
module_param(time, int, 0644); 
int delay; 
struct workqueue_struct* wq; 
struct work_struct task; 
struct timer_list timer;  /* timer */ 

long ioctl(struct file *filp, unsigned int cmd, unsigned long args) { 
    switch (cmd) { 
     case REGISTER: 
      add_timer(&timer); 
      return 0; 
     case UNREGISTER: 
      del_timer_sync(&timer); 
      return 0; 
    } 
} 

static void doJob(struct work_struct *work) { 
    printk(KERN_EMERG "\ndoJob\n"); 
    mod_timer(&timer, jiffies + delay); 

} 
void update(unsigned long arg) { 
    queue_work(wq, &task); 
} 
struct file_operations fop = { 
    .owner = THIS_MODULE, 
    .unlocked_ioctl = ioctl 
}; 

static struct miscdevice dev = { 
    .minor = MISC_DYNAMIC_MINOR, 
    .name = "timer", 
    .fops = &fop 
}; 


static int __init init(void) 
{ 
    delay = HZ * time/1000; 
    if (delay < 1) { 
     printk(KERN_EMERG "time param is too small\n"); 
     return -1; 
    } 

    init_timer(&timer); 
    timer.data = 0; 
    timer.function = update; 
    timer.expires = jiffies + delay; 

    if (misc_register(&dev) < 0) { 
     printk(KERN_EMERG "error registering misc device\n"); 
     return -1; 
    } 
    wq = create_workqueue("timer_task"); 
    INIT_WORK(&task, doJob); 

    return 0; 
} 

static void __exit fini(void) 
{ 

    misc_deregister(&dev); 
    printk(KERN_EMERG "deregistered\n"); 

} 

module_init(init); 
module_exit(fini); 

답변

2

del_timer_sync()docs이 말 .

다른 변수를 유지하기 만하면 timer_active입니다. 타이머를 시작하기 전에이 값을 true로 설정하고 타이머를 삭제하기 전에 false로 설정하십시오. 그런 다음 timer_active이 참일 때만 타이머를 재 스케줄합니다. 이 명령으로 del_timer_sync()이 반환 된 후에 더 이상 타이머가 실행되지 않을 것입니다.

관련 문제