【ky开元棋盘网址】
Linux 事变行列 workqueue 是什么鬼?
发布日期:2022-08-07 03:06    点击次数:72

 

目录 事变行列是什么  驱动顺序  编译、测试

别人的经历,我们的路子!

Linux中缀处置惩罚可用下图总结:

图中形貌了中缀处置惩罚中的下半部份都有哪些机制,以及怎么样痛处置论的业务场景、限定条件来举行抉择。

可以或许看出:这些差别的完成之间,有些是重复的,或许是互相庖代的纠葛。

也正因为此,它们之间的运用要领险些是迥然不同,起码是在API接口函数的运用要领上,从运用这的角度来看,都是极度近似的。

这篇文章,我们就经由过程理论的代码操作,来演示一下事变行列(workqueue)的运用要领。

事变行列是什么

事变行列是Linux操作体系中,举行中缀下半部份处置惩罚的首要要领!

从名称上可以或许猜到:一个事变行列就彷佛业务层经常使用的音讯行列同样,内里寄放着良多的事变项等待着被处置惩罚。

事变行列中有两个首要的组织体:事变行列(workqueue_struct) 和 事变项(work_struct): 

struct workqueue_struct {      struct list_head        pwqs;           /* WR: all pwqs of this wq */      struct list_head        list;           /* PR: list of all workqueues */      ...      char                    name[WQ_NAME_LEN]; /* I: workqueue name */      ...      /* hot fields used during co妹妹and issue, aligned to cacheline */      unsigned int            flags ____cacheline_aligned; /* WQ: WQ_* flags */      struct pool_workqueue __percpu *cpu_pwqs; /* I: per-cpu pwqs */      struct pool_workqueue __rcu *numa_pwq_tbl[]; /* PWR: unbound pwqs indexed by node */  };  
struct work_struct {          atomic_long_t data;          struct list_head entry;          work_func_t func;   // 指向处置惩罚函数  #ifdef CONFIG_LOCKDEP                                                                                            struct lockdep_map lockdep_map;  #endif  }; 

在内核中,事变行列中的全体事变项,是经由过程链表串在一起的,并且等待着操作体系中的某个线程挨个取进去处置惩罚。

这些线程,可以是由驱动顺序经由过程 kthread_create 创立的线程,也可以是由操作体系事后就创立好的线程。

这里就奔忙及到一个取舍的成就了。

假定我们的处置惩罚函数很俭朴,那末就没有须要创立一个零丁的线程来处置惩罚了。

启事有二:

  创立一个内核线程是很淹灭资源的,假定函数很俭朴,很快执行终止当前再敞开线程,太划不来了,得失相当;   假定每一个驱动顺序编写者都毫无控制地创立内核线程,那末内核中将会存在大量毋庸要的线程,游戏快讯固然了本质上照旧体系资源斲丧和执行效劳的成就;

为了不这类环境,是以操作体系就为我们事后创立好一些事变行列和内核线程。

我们只有要把须要处置惩罚的事变项,间接增加到这些事后创立好的事变行列中就能了,它们就会被响应的内核线程取进去处置惩罚。

譬以下面这些事变行列,就是内核默认创立的(include/linux/workqueue.h): 

/*   * System-wide workqueues which are always present.   *   * system_wq is the one used by schedule[_delayed]_work[_on]().   * Multi-CPU multi-threaded.  There are users which expect relatively   * short queue flush time.  Don't queue works which can run for too   * long.   *   * system_highpri_wq is similar to system_wq but for work items which   * require WQ_HIGHPRI.   *   * system_long_wq is similar to system_wq but may host long running   * works.  Queue flushing might take relatively long.   *   * system_unbound_wq is unbound workqueue.  Workers are not bound to   * any specific CPU, not concurrency managed, and all queued works are   * executed i妹妹ediately as long as max_active limit is not reached and   * resources are available.   *   * system_freezable_wq is equivalent to system_wq except that it's   * freezable.   *   * *_power_efficient_wq are inclined towards saving power and converted   * into WQ_UNBOUND variants if 'wq_power_efficient' is enabled; otherwise,   * they are same as their non-power-efficient counterparts - e.g.   * system_power_efficient_wq is identical to system_wq if   * 'wq_power_efficient' is disabled.  See WQ_POWER_EFFICIENT for more info.   */  extern struct workqueue_struct *system_wq;  extern struct workqueue_struct *system_highpri_wq;  extern struct workqueue_struct *system_long_wq;  extern struct workqueue_struct *system_unbound_wq;  extern struct workqueue_struct *system_freezable_wq;  extern struct workqueue_struct *system_power_efficient_wq;  extern struct workqueue_struct *system_freezable_power_efficient_wq; 

以上这些默认事变行列的创立代码是(kernel/workqueue.c): 

int __init workqueue_init_early(void)  {      ...          system_wq = alloc_workqueue("events", 0, 0);      system_highpri_wq = alloc_workqueue("events_highpri", WQ_HIGHPRI, 0);                            system_long_wq = alloc_workqueue("events_long", 0, 0);      system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND,                                              WQ_UNBOUND_MAX_ACTIVE);      system_freezable_wq = alloc_workqueue("events_freezable",                                                WQ_FREEZABLE, 0);      system_power_efficient_wq = alloc_workqueue("events_power_efficient",                                                WQ_POWER_EFFICIENT, 0);      system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient",                                                WQ_FREEZABLE | WQ_POWER_EFFICIENT,                                                0);      ...  } 

其他,因为事变行列 system_wq 被运用的频次很高,是以内核就封装了一个俭朴的函数(schedule_work)给我们运用: 

/**   * schedule_work - put work task in global workqueue   * @work: job to be done   *   * Returns 


上一篇:50岁杨钰莹才是真会穿!小香风西装搭牛仔裤,优雅、时髦两不误
下一篇:三款值得推选的 Java 云框架