kworker/n 和 events/n 之间的区别

kworker/n 和 events/n 之间的区别

我正在学习内核如何处理中断。
阅读石超的笔记,我发现events/n线程处理工作队列。
同时,网上的一些文档(例如,这个帖子),这样说

“kworker”是内核工作线程的占位符进程,它执行内核的大部分实际处理,特别是在存在中断、计时器、I/O 等的情况下。

在我看来它们很相似,我有点困惑:events/nthreads 和kworkerthreads 一样吗?如果一样,是否events/n已重命名为?如果不是,那么和kworker有什么区别?events/nkworker

我可以通过 找到kworker(ex, kworker/1:0) htop,但看不到events/n

答案1

我想我可能对此有一个答案。摘要似乎是名称发生了变化,尽管我还没有找到相关的文档。

细节:

世超的笔记是根据书本做的笔记Linux 内核开发 作者:Robert Love。该书基于内核版本 2.6.34。注释中的代码片段与文件中的代码匹配内核/工作队列.c对于该版本:

/*
 * The per-CPU workqueue (if single thread, we always use the first
 * possible cpu).
 */
struct cpu_workqueue_struct {

        spinlock_t lock;

        struct list_head worklist;
        wait_queue_head_t more_work;
        struct work_struct *current_work;

        struct workqueue_struct *wq;
        struct task_struct *thread;
} ____cacheline_aligned;

/*
 * The externally visible workqueue abstraction is an array of
 * per-CPU workqueues:
 */
struct workqueue_struct {
        struct cpu_workqueue_struct *cpu_wq;
        struct list_head list;
        const char *name;
        int singlethread;
        int freezeable;         /* Freeze threads during suspend */
        int rt;
#ifdef CONFIG_LOCKDEP
        struct lockdep_map lockdep_map;
#endif
};

Linux 版本似乎使用的是初始化工作队列创建工作队列的函数:

void __init init_workqueues(void)
{
        ...
        keventd_wq = create_workqueue("events");
}

Robert Love 的书第 154 页“创建队列”部分说道:

您可以通过一个简单的函数创建一个新的工作队列和关联的工作线程: struct workqueue_struct *create_workqueue(const char *name);参数name用于命名内核线程

因此,上面的代码似乎很能说明为什么工作线程被命名为“事件”。

较新的代码(查看 4.19)有一些差异。首先,工作队列结构体的范围要广泛得多,并且cpu_workqueue_struct不复存在。现在有了池,并且工作队列工作线程的创建是由名为的函数完成的创建工人在一个水池里。在该函数内部,创建了“kworker/%s”kthread,如下面的代码片段所示:

/**
 * create_worker - create a new workqueue worker
 * @pool: pool the new worker will belong to
 *
 * Create and start a new worker which is attached to @pool.
 *
 * CONTEXT:
 * Might sleep.  Does GFP_KERNEL allocations.
 *
 * Return:
 * Pointer to the newly created worker.
 */
static struct worker *create_worker(struct worker_pool *pool)
{
        ...
        worker->task = kthread_create_on_node(worker_thread, worker, pool->node,
                                              "kworker/%s", id_buf);
        ...
}

所以,这就是我所能得到的。如果有人有更精确或更正的意见,我很乐意听到他们的声音。

至于工作队列的确切信息,位于这个内核文档

相关内容