<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Linux內核實現透視---kthread_work

      內核線程工作隊列

      內核線程工作隊列和普通工作隊列看著十分相似,很多抽象概念如work和worker等都很相同并且執行對象也都是內核線程。不同的是內核線程工作隊列沒有普通工作隊列的線程池概念一個 worker(工作者(工作組))對應到一個實際的內核線程,這個內核線程會按順序依次執行worker上的每一個work。這個worker 對應的內核線程是當前CPU節點上的,因此可以推導出這個worker下的work都是在同一個CPU上執行的--TODO1:負載均衡會遷移嗎?來看下數據結構:

      工作組(工作者)

      struct kthread_worker {
      	unsigned int		flags;
          // 隊列操作的鎖
      	spinlock_t		lock;
          // work 隊列
      	struct list_head	work_list;
          // delay work 隊列
      	struct list_head	delayed_work_list;
          //worker 對應的內核線程
      	struct task_struct	*task;
          // 當前正在處理的work
      	struct kthread_work	*current_work;
      };
      

      一個工作(work)

      struct kthread_work {
      	struct list_head	node;
      	kthread_work_func_t	func;
      	struct kthread_worker	*worker;
      	/* Number of canceling calls that are running at the moment. */
      	int			canceling;
      };
      

      一個工作組中包括兩個工作list,一個是普通的工作list另一個是延時執行的工作隊列。使用時user可以自己定義內核線程工作者線程的實現,而默認的內核工作隊列處理程序由內核在kernel\kthread.c 文中實現在kthread_worker_fn 中如下,當調用kthread_create_worker_on_cpu 創建內核線程時實際上這個就是這個內核線程的執行體,當然也可以通過kthread_run 宏函數并將這個函數作為第一個入參傳入,此時內核線程的執行體也是如下的接口。

      內核線程工作隊列處理

      int kthread_worker_fn(void *worker_ptr)
      {
      	struct kthread_worker *worker = worker_ptr;
      	struct kthread_work *work;
      
      	/*
      	 * FIXME: Update the check and remove the assignment when all kthread
      	 * worker users are created using kthread_create_worker*() functions.
      	 */
      	WARN_ON(worker->task && worker->task != current);
      	worker->task = current;
          //休眠相關的
      	if (worker->flags & KTW_FREEZABLE)
      		set_freezable();
          //未持有鎖時內核線程可以被中斷
      repeat:
      	set_current_state(TASK_INTERRUPTIBLE);	/* mb paired w/ kthread_stop */
          //內核線程要停止必須檢查這一項,負責就僅能使用使能信號處理的機制停止內核線程
      	if (kthread_should_stop()) {
      		__set_current_state(TASK_RUNNING);
      		spin_lock_irq(&worker->lock);
      		worker->task = NULL;
      		spin_unlock_irq(&worker->lock);
      		return 0;
      	}
          //尋找第一個加入隊列的work
      	work = NULL;
      	spin_lock_irq(&worker->lock);
      	if (!list_empty(&worker->work_list)) {
      		work = list_first_entry(&worker->work_list,
      					struct kthread_work, node);
      		list_del_init(&work->node);
      	}
      	worker->current_work = work;
      	spin_unlock_irq(&worker->lock);
          //找到了第一個work開始處理
      	if (work) {
      		__set_current_state(TASK_RUNNING);
      		work->func(work);
          //沒有work需要處理則放棄時間片
      	} else if (!freezing(current))
      		schedule();
          //未使能KTW_FREEZABLE時可能調用這里
      	try_to_freeze();
      	cond_resched();
      	goto repeat;
      }
      

      這是內核工作線程的工作的處理過程,細心點就揮發下這里僅僅處理了普通的work,而delay_workw未進行處理。實際上delay work不需要內核線程處理,相反的延時工作的調用依賴內核的定時器timer由定時器到期時回調從而進行處理。

      使用

      內核線程的工作隊列使用時可以直接使用內核定義的worker,也可以自己創建對應的kworker 使用獨立內核線程處理works 從而保證work的及時性。
      示例:

      struct kthread_worker	kworker;
      struct task_struct		*kworker_task;
      struct kthread_work		work;
      //初始化工作組
      kthread_init_worker(&kworker);
      //創建一個內核線程并運行kthread_worker_fn 參數是kworker 后面的參數是線程名稱
      kworker_task = kthread_run(kthread_worker_fn, &kworker,"%s", "xxxx");
      //初始化線程
      kthread_init_work(&work, kthread_work_func_t fun);
      //向工作組添加一個工作,這個接口可能喚醒內核線程,執行完成后這個工作就被刪除了
      kthread_queue_work(kworker, &work);
      //添加一個延時內核工作
      kthread_queue_delayed_work(kworker, &work,delay)
      //停止內核線程,依賴內核線程中調用(kthread_should_stop)檢查,這個接口會阻塞直到內核線程退出
      kthread_stop(kworker_task)
      

      內部實現

      1. kworker的創建
        當新建一個內核工作線程時,如kthread_run 接口,此時會喚醒內內核的kthreadadd 線程,有這個線程完成新內核工作線程的創建。
      2. kworker 銷毀
        當驅動 退出需要銷毀kthread時,通過調用 kthread_destroy_worker接口來完成,這個接口的內部實現流程是
        a. flush 這個worker queue上的所有work
        b. 停止worker對應的線程
        c. 釋放worker mem
        a 步驟的實現就是通過在當前worker上添加一個特殊的work,等待這個work處理完成,此時就說明所有的work都被處理完成了。然后就可以執行后續
        的銷毀動作。

      API

      除了上面的經常使用API接口外還有一些不常用的API 接口這里簡單記錄下

      //釋放進程控制塊內存
      void free_kthread_struct(struct task_struct *k);
      //將線程綁定到指定cpu上
      void kthread_bind(struct task_struct *k, unsigned int cpu);
      //將線程綁定到幾個cpu上用掩碼
      void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask);
      //標記內核線程停止并等待線程停止
      int kthread_stop(struct task_struct *k);
      //檢查線程是否要停止
      bool kthread_should_stop(void);
      //檢查線程是否要park
      bool kthread_should_park(void);
      //睡眠使用停止模式
      bool kthread_freezable_should_stop(bool *was_frozen);
      //獲取線程data
      void *kthread_data(struct task_struct *k);
      //
      void *kthread_probe_data(struct task_struct *k);
      //標記線程park
      int kthread_park(struct task_struct *k);
      //取消標記park
      void kthread_unpark(struct task_struct *k);
      // 等待park標記是否清除
      void kthread_parkme(void);
      //內核線程的管理接口
      int kthreadd(void *unused);
      

      總結

      總的來說內核線程隊列的實現和普通工作隊列[http://www.rzrgm.cn/w-smile/p/13499279.html]的相比實現上簡單的一些。使用內核線程的更加清晰明了,內核在kthreadd維護了內核線程隊列,各個worker的執行體維護了自己的work list。內核線程工作隊列和普通工作隊列相比沒有線程池的概念因此內核線程工作隊列中的work是不支持并發,因此設計work 函數時不用考慮重入的場景。普通工作隊列的的實現上增加了工作組的線程池的概念從而支持并發(不同work并發),二者的區別和共同點都很明顯。
      共同點:本質上都是內核線程來處理的;也都支持延遲工作。
      不同點:增加了線程池的管理,所以工作隊列中work可能會被多個內核線程處理,因此會出現work(不同work)并發,同時消耗的系統資源也更加多,但是對于多work并發的能力更強。

      posted @ 2021-02-15 14:06  Little_Village  閱讀(1091)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 玩弄放荡人妻少妇系列| 天天躁夜夜躁狠狠综合| 成人精品自拍视频免费看| 亚洲av无码精品色午夜蛋壳| 欧美成人看片一区二区三区尤物| 久久亚洲精品天天综合网| 无码人妻斩一区二区三区| 人妻熟女一区二区aⅴ向井蓝| 国产成人精品性色av麻豆| 97成人碰碰久久人人超级碰oo| 久久久精品人妻一区二区三区蜜桃| 久久国产精品精品国产色婷婷| 国内视频偷拍久久伊人网| 亚洲鸥美日韩精品久久| 永久无码天堂网小说区| 天堂av最新版中文在线| 久久国产精品老人性| 国产精品流白浆无遮挡| 亚洲精品成人一二三专区| 中文字幕有码高清日韩| 男女吃奶做爰猛烈紧视频| 亚洲精品日本久久久中文字幕| 尤物视频色版在线观看| 国产精品白浆在线观看免费| 久久国产综合色免费观看| 欧美日韩不卡视频合集| 日韩精品一区二区三区激情视频 | 亚洲国产午夜理论片不卡| 深夜av免费在线观看| 岛国中文字幕一区二区| 国产日女人视频在线观看| 久久综合色之久久综合| 最新中文字幕av无码专区不| 亚洲精品一区二区麻豆| 日韩一区在线中文字幕| 日韩无人区码卡1卡2卡| 成人精品区| 久久三级国内外久久三级| 亚洲成人精品综合在线 | 在线观看中文字幕国产码| 国产日韩av一区二区在线|