Chinaunix首页 | 论坛 | 博客
  • 博客访问: 693495
  • 博文数量: 90
  • 博客积分: 3225
  • 博客等级: 少校
  • 技术积分: 1200
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-20 11:04
个人简介

菩提本无树,明镜变非台 本来无一物,何处惹尘埃

文章分类

全部博文(90)

文章存档

2015年(1)

2014年(12)

2013年(15)

2012年(31)

2011年(8)

2010年(23)

分类: LINUX

2012-04-10 15:02:34

  延迟可以分为长延迟和短延迟,但其划分界限并不是很清晰,一般以jiffies为单位进行的延迟通常认为长延迟,而小于jiffy的延迟则认为是短延迟;在内核中有很多方法实现延迟操作,但有些方法并不可取,例如对于长延迟来说忙等待操作是不可取的;所以这里列出一些不错的方案。

1 长延迟
  对于长延迟,可以使用等待队列机制来实现,内核提供的接口如下:
#include  
long wait_event_timeout(wait_queue_head_t, condition, long timeout); /* 休眠时不可中断 */ 
long wait_event_interruptible_timeout(wait_queue_head_t, condition, 
                                      long timeout);/*可中断*/

#include  
signed long schedule_timeout(signed long timeout); /* 这个函数用于要使用wake_up这种情况 */

  上述函数实际是些宏;其中的参数"timeout"表示要等待的"jiffies"值,不是相对时间值。调用此类函数会使进程休眠,只有等到超时或者中断才会返回。
 完整使用示例
    #include  
    #include  
    #include  /* jiffies */ 
    #include     /* waitqueue */ 
    #include  
    #include  /* create_proc_read_entry() */ 
    MODULE_LICENSE("Dual BSD/GPL"); 
    int wait_queue_proc(char *buf, char **start, off_t offset, 
                        int len, int *eof, void *data) 
    { 
        unsigned long j0, j1; 
        wait_queue_head_t wait;       /* 定义一个等待队列 */ 
        init_waitqueue_head(&wait);   /* 初始化等待队列 */ 
        j0 = jiffies; 
        wait_event_interruptible_timeout(wait, 0, HZ); /* 设置延迟1秒 */ 
        j1 = jiffies; 
        len = sprintf(buf,"%9ld %9ld\n",j0,j1); 
        *start = buf; 
        return len; 
    } 
    static __init int main_init(void) 
    { 
        create_proc_read_entry("waitqueue", 0, NULL, wait_queue_proc, NULL); 
        return 0; 
    } 
    static __exit void main_exit(void) 
    { 
        remove_proc_entry("wait_queue",NULL); 
    } 
    module_init(main_init); 
    module_exit(main_exit);
  如果要使用schedule_timeout的话,"wait_queue_proc"内容应为
    unsigned long j0, j1; 
    j0 = jiffies; 
    set_current_state(TASK_INTERRUPTIBLE);   /* 设置当前进程状态 */ 
    schedule_timeout(HZ);  /* 延迟1秒 */ 
    j1 = jiffies; 
    len = sprintf(buf,"%9ld %9ld\n",j0,j1); 
    *start = buf; 
    return len;
 这里用到"proc"文件机制;加载该模块后,使用"$dd bs=20 count=5 < /proc/waitqueue",输出结果如下

  如果想使用"$cat /proc/waitqueue"输出,那么你需将"wait_queue_proc"函数的"return len"改成"return PAGE_SIZE",否则有得你等了。

 2 短延迟
  短延迟不依赖时钟滴答来实现的。
  使用软件循环来实现的机制 
#include  
void ndelay(unsigned long nsecs); /* 纳秒级 */ 
void udelay(unsigned long usecs); /* 微秒级 */ 
void mdelay(unsigned long msecs); /* 毫秒级 */ 

 这些函数实现延迟的时间不会少于给定的时间值;
 由于这些函数是使用忙等待实现的,所以运行该类函数时无法运行其他任务。为了避免这种情况,内核提供另一种接口,这种接口是使用进程休眠来实现的,该接口如下 
void msleep(unsigned int millisecs); /* 毫秒级,不可中断 */ 
unsigned long msleep_interruptible(unsigned int millisecs); /* 毫秒级,可中断 */ 
void ssleep(unsigned int seconds); /* 秒级,不可中断 */ 

示例,将上面示例的wait_queue_proc函数改成如下
int wait_queue_proc(char *buf, char **start, off_t offset, 
                        int len, int *eof, void *data) 
    { 
        unsigned long j0,j1; 
        j0 = jiffies; 
        mdelay(1000); /* 1秒 */
        /* 或者是
         ssleep(1);
         */
        j1 = jiffies;
        len = sprintf(buf,"%9ld %9ld\n",j0,j1);
        *start = buf;
        return len;
    }
如果能容忍比所请求更长的延迟,则应使用"schedule_timeout"、"ssleep"。("ldd3"中写道)

注: 转载时请注明出自:add358.blog.chinaunix.net
 
阅读(2244) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~