jiffies_64unsigned long jiffies使用jiffies計">

多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > 互聯(lián)網(wǎng) > 《Linux Device Drivers》 第七章 時間、延時及延緩操作――note

《Linux Device Drivers》 第七章 時間、延時及延緩操作――note

來源:程序員人生   發(fā)布時間:2014-10-13 02:03:27 閱讀次數(shù):3081次
  • 度量時間差
    • 內(nèi)核通過定時器中斷來跟蹤時間流
    • 時鐘中斷由系統(tǒng)定時硬件以周期性的間隔產(chǎn)生,這個間隔由內(nèi)核根據(jù)HZ的值設(shè)定,在常見的x86 PC平臺上,默認(rèn)定義為1000
    • <linux/param.h>
    • <linux/timex.h>
    • jiffies_64
    • unsigned long jiffies
    • 使用jiffies計數(shù)器
      • <linux/jiffies.h>
        • int time_after(unsigned long a, unsigned long b);
        • int time_before(unsigned long a, unsigned long b);
        • int time_after_eq(unsigned long a, unsigned long b);
        • int time_before_eq(unsigned long a, unsigned long b);
      • 通常只需要包含<linux/sched.h>
      • diff = (long)t2 -(long)t1
      • msec = diff * 1000 / HZ
      • <linux/times.h
        • unsigned long timespec_to_jiffies(struct timespec *value);
        • void jiffies_to_timespec(unsigned long jiffies, struct timespec *value);
        • unsigned long timeval_to_jiffies(struct timeval *value);
        • void jiffies_to_timeval(unsigned long jiffies, struct timeval *value);
      • u64 get_jiffies_64(void);
      • <linux/types.h>
      • proc/interrupts
    • 處理器特定的寄存器
      • 最有名的計數(shù)器寄存器就是TSC
      • <asm/msr.h>
        • rdtsc(low32, high32);
        • rdtscl(low32);
        • rdtscl1(var64);
      • <linux/timex.h>
        • cycles_t get_cycles(void);
        1. define rdtscl(dest) __asm__ __volatile__(“mfs0 %0,$9; nop” : “=r” (dest))

  • 獲取當(dāng)前時間
    • 內(nèi)核提供將墻鐘時間轉(zhuǎn)換為jiffies值的函數(shù)
    • <linux/time.h>
      • unsigned long mktime(unsigned int year, unsigned int mon, unsigned int day, unsigned int hour, unsigned int min, unsigned int sec);
      • void do_gettimeofday(struct timeval *tv);
      • struct timespec current_kernel_time(void);
  • 延遲執(zhí)行
    • 長延遲
      • 忙等待
        • while (time_before(jiffies, j1)) cpu_relax();
      • 讓出處理器
        • 在不需要CPU時主動釋放CPU
        • <linux/sched.h>
        • while (time_before(jiffies, j1)) schedule();
      • 超時
        • <linux/wait.h>
          • long wait_event_timeout(wait_queue_head_t q, condition c, long timeout);
          • long wait_event_interruptible_timeout(wait_queue_head_t q, condition c, long timeout);
          • timeout值表示的是要等的jiffies值,而不是絕對時間值
          • 如果超時到期,兩個函數(shù)返回0;如果進程由其他事件喚醒,則返回剩余的延遲實現(xiàn)
        • <linux/sched.h>
          • signed long schedule_timeout(signed long timeout);
          • set_current_state(TASK_INTERRUPTIBLE);
          • schedule_timeout(delay);
    • 短延遲
      • <linux/delay.h>
        • void ndelay(unsigned long nsecs);
        • void udelay(unsigned long usecs);
        • void mdelay(unsigned long msecs);
        • 這三個延遲函數(shù)均是忙等待函數(shù)
        • unsigned long msleep_interruptible(unsigned int millisecs);
        • void ssleep(unsigned int seconds);
  • 內(nèi)核定時器
    • 一個內(nèi)核定時器是一個數(shù)據(jù)結(jié)構(gòu),它告訴內(nèi)核在用戶定義的時間點使用用戶定義的參數(shù)來執(zhí)行一個用戶定義的函數(shù)
    • 內(nèi)核定時器常常是作為“軟件中斷”的結(jié)果而運行的
    • 如果處于進程上下文之外,則必須遵守如下規(guī)則
      • 不允許訪問用戶空間
      • current指針在原子模式下是沒有任何意義的,也是不可用的
      • 不能執(zhí)行休眠或調(diào)度
    • <asm/hardirq.h>
      • in_interrupt()
      • in_atomic()
    • 任務(wù)可以將自己注冊以在稍后的時間重新運行
    • 即使在單處理器系統(tǒng)上,定時器也會是競態(tài)的潛在來源
    • 定時器API
      • <linux/timer.h>
        • struct timer_list
          • unsigned long expires;
          • void (*function)(unsigned long);
          • unsigned long data;
        • void init_timer(struct timer_list *time);
        • struct timer_list TIMER_INITIALIZER(_function, _expires, _data);
        • void add_timer(struct timer_list *timer);
        • int del_timer(struct timer_list *timer);
        • expires字段表示期望定時器執(zhí)行的jiffies值
        • int mod_timer(struct timer_list *timer, unsigned long expires);
        • int del_timer_sync(struct timer_list *timer);
        • int timer_pending(const struct timer_list *timer);
    • 內(nèi)核定時器的實現(xiàn)
      • 內(nèi)核定時器的實現(xiàn)要滿足如下需求及假定
        • 定時器的管理必須盡可能做到輕量級
        • 其設(shè)計必須在活動定時器大量增加時具有很好的伸縮性
        • 大部分定時器會在最多幾秒或者幾分鐘內(nèi)到期,而很少存在長期延遲的定時器
        • 定時器應(yīng)該在注冊它的同一CPU上運行
      • 不管何時內(nèi)核代碼注冊了一個定時器,其操作最終會由internal_add_timer(定義在kernel/timer.c)執(zhí)行
      • 級聯(lián)表的工作方式如下
        • 如果定時器在接下來的0~255的jiffiew中到期,由該定時器就會被添加到256個鏈表中的一個(取決于expires字段的低8位值)
        • 如果定時器在較遠(yuǎn)的未來到期(但在16384個jiffies之前),則該定時器會被添加到64個鏈表之一(取決于expires字段的9~14位)
        • 對更遠(yuǎn)將來的定時器,相同的技巧用于15~20位、21~26位以及27~31位
        • 如果定時器的expires字段代表了更遠(yuǎn)的未來,則利用延遲0xfffffff做散列運算,而在過去時間內(nèi)到期的定時器會在下一個定時器滴答時被調(diào)度
      • 當(dāng)__run_times被激發(fā)時,它會執(zhí)行當(dāng)前定時器滴答上的所有掛起的定時器
  • tasklet
    • 中斷管理中大量使用了這種機制
    • 始終在中斷期間運行,始終會在調(diào)度它的同一CPU運行,接收一個unsigned long參數(shù)
    • 不能要求tasklet在某個給定時間執(zhí)行
    • <linux/interrupt.h>
      • struct tasklet_struct
        • void (*func)(unsigned long);
        • unsigned long data;
      • void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);
      • DECLARE_TASKLET(name, func, data);
      • DECLARE_TASKLET_DISABLED(name, func, data);
    • 有意思的特性
      • 一個tasklet可以稍后被禁止或者重新啟用;只有啟用的次數(shù)和禁止的次數(shù)相同時,tasklet才會被執(zhí)行
      • 和定時器類似,tasklet可以注冊自己本身
      • tasklet可被調(diào)度以在通常的優(yōu)先級或者高優(yōu)先級執(zhí)行
      • 如果系統(tǒng)負(fù)荷不重,則tasklet會立即得到執(zhí)行,但始終不會晚于下一個定時器滴答
      • 一個tasklet可以和其他tasklet并發(fā),但對自身來講是嚴(yán)格串行處理的
    • void tasklet_disable(struct tasklet_struct *t);
    • void tasklet_disable_nosync(struct tasklet_struct *t);
    • void tasklet_enable(struct tasklet_struct *t);
    • void tasklet_schedule(struct tasklet_struct *t);
    • void tasklet_hi_schedule(struct tasklet_struct *t);
    • void tasklet_kill(struct tasklet_struct *t);
    • tasklet的實現(xiàn)在kernel/softirq.c中
  • 工作隊列
    • 與tasklet區(qū)別
      • tasklet在軟件中斷上下文中運行,因此,所有的tasklet代碼都必須是原子的。相反,工作隊列函數(shù)在一個特殊內(nèi)核進程的上下文中運行,因此它們具有更好的靈活性。尤其是,工作隊列函數(shù)可以休眠
      • tasklet始終運行在被初始提交的同一處理器上,但這只是工作隊列的默認(rèn)方式
      • 內(nèi)核代碼可以請求工作隊列函數(shù)的執(zhí)行延遲給定的時間間隔
    • 工作隊列函數(shù)可具有更長的延遲并且不必原子化
    • <linux/workqueue.h>
      • struct workqueue_struct
      • struct workqueue_struct *create_workqueue(const char *name);
      • struct workqueue_struct *create_singlethread_workqueue(const char *name);
      • struct work_struct
      • DECLARE_WORK(name, void (*function)(void*), void *data);
      • INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
      • PREPARE_WORK(struct work_struct *work, void (*function)(void *), void *data);
      • int queue_work(struct workqueue_struct *queue, struct work_struct *work);
      • int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work, unsigned long delay);
      • 以上兩個函數(shù)返回值為非零時意味著給定的work_struct結(jié)構(gòu)已經(jīng)等待在該隊列中
      • int cancel_delayed_work(struct work_struct *work);
        • 該入口項在開始執(zhí)行前被取消,則返回非零值
      • void flush_workqueue(struct workqueue_struct *queue);
      • void destroy_workqueue(struct workqueue_struct *queue);
    • 共享隊列
      • int schedule_work(struct work_struct *work);
      • void flush_scheduled_work(void)

小結(jié):1. Linux基于時鐘中斷跟蹤,系統(tǒng)時間流。

           2.定時器、任務(wù)必須遵循在原子上下文,定時器可以指定將來的調(diào)度時間,任務(wù)無法指定執(zhí)行的時間。

           3.工作隊列,調(diào)度的函數(shù)可以休眠。

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 456在线视频 | porn在线视频一区二区 | 国产中的精品suv一区二区 | 综合欧美日韩 | 伊人成综合 | 亚洲欧美国产精品专区久久 | 图片区 小说区 | 精品久久国产 | 手机看片日韩高清国产欧美 | 日韩精品免费 | 日本一区二区三区免费高清在线 | xyx性爽欧美视频 | 欧美性猛交黑人xxxx | 欧美色图狠狠干 | 毛片官网 | 欧美手机看片 | 亚洲 自拍 另类 欧美 综合 | 性xxxx黑人与亚洲 | 日韩欧美视频在线一区二区 | 波霸欧美性猛交xxxxxx | 精品久久久久久中文字幕专区 | 逼逼爱爱 | 久久伊人婷婷 | 免费爱爱视频网站 | 免费国产h视频在线观看 | 国产三区二区 | 国产精品高清一区二区三区 | 久久伊人成人网 | 亚洲专区欧美 | 大香网伊人久久综合网2020 | 亚洲免费不卡 | 欧美日韩一区二区三区久久 | 国产免费a v吧在线观看不卡 | 一级做a爰片久久毛片欧美 一级做a爰片久久毛片人呢 | 天天更新天天久久久更新影院 | 欧美日韩亚洲高清不卡一区二区三区 | 男人边吃奶边摸下面好爽视频 | 激情片段视频 | 国产午夜精品久久久久九九 | 性欧美高清极品猛交 | 日本1区2区 |