If you want to pass data to your work queue function, just embed the work_struct structure inside your own data structure and use container_of inside your work function to retrieve it.

As for a simple example, the kernel is full of it - just git grep work_struct. You can look at drivers/cpufreq/cpufreq.c (handle_update function) for a simple example. The article below also embeds an example at the end, but it does not use container_of and instead relies on the fact that the first member of a structure has the same address as its parent:

http://www.ibm.com/developerworks/linux/library/l-tasklets/index.html

Answer from Gnurou on Stack Overflow
🌐
Linux Kernel
docs.kernel.org › core-api › workqueue.html
Workqueue — The Linux Kernel documentation
When such an asynchronous execution context is needed, a work item describing which function to execute is put on a queue. An independent thread serves as the asynchronous execution context. The queue is called workqueue and the thread is called worker.
🌐
EmbeTronicX
embetronicx.com › tutorials › linux › device-drivers › workqueue-in-linux-kernel
Workqueue in Linux Kernel Part 1 – Linux Device Driver Tutorial Part 14
September 24, 2023 - Work queues are added in the Linux kernel 2.6 version. Work queues are a different form of deferring work. Work queues defer work into a kernel thread; this bottom half always runs in the process context.
🌐
GitHub
github.com › torvalds › linux › blob › master › kernel › workqueue.c
linux/kernel/workqueue.c at master · torvalds/linux
system_dfl_wq = alloc_workqueue("events_unbound", WQ_UNBOUND, WQ_MAX_ACTIVE);
Author   torvalds
🌐
O'Reilly
oreilly.com › library › view › understanding-the-linux › 0596005652 › ch04s08.html
4.8. Work Queues - Understanding the Linux Kernel, 3rd Edition [Book]
November 17, 2005 - The work queues have been introduced ... used in Linux 2.4. They allow kernel functions to be activated (much like deferrable functions) and later executed by special kernel threads called worker threads ....
Authors   Daniel P. BovetMarco Cesati
Published   2005
Pages   942
🌐
Linux Kernel
kernel.org › doc › html › v4.14 › core-api › workqueue.html
Concurrency Managed Workqueue (cmwq) — The Linux Kernel documentation
When such an asynchronous execution context is needed, a work item describing which function to execute is put on a queue. An independent thread serves as the asynchronous execution context. The queue is called workqueue and the thread is called worker.
🌐
Linux Kernel Labs
linux-kernel-labs.github.io › refs › heads › master › labs › deferred_work.html
Deferred work — The Linux Kernel documentation
Kernel threads are the basis of the workqueue mechanism. Essentially, a kernel thread is a thread that only runs in kernel mode and has no user address space or other user attributes. ... #include <linux/kthread.h> struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, ...
🌐
Paper Checker
hub.paper-checker.com › blog › multitasking-in-the-linux-kernel-an-in-depth-guide-to-workqueues
Multitasking in Linux Kernel: Exploring Workqueues
January 16, 2025 - Workqueues are a flexible mechanism in the Linux kernel that allow tasks to be queued and executed by worker threads in the background.
Find elsewhere
🌐
martinuke0's Blog
martinuke0.github.io › posts › understanding kworker: the heartbeat of linux kernel workqueues
Understanding kworker: The Heartbeat of Linux Kernel Workqueues | martinuke0's Blog
March 27, 2026 - Introduction If you have ever peered into a running Linux system with tools like top, htop, or ps, you might have noticed a set of processes named kworker/*. These processes are not user‑space daemons; they are kernel threads that drive the workqueue subsystem, a core mechanism that lets the kernel defer work to a later time or to a different context.
🌐
LWN.net
lwn.net › Articles › 11360
Details of the workqueue interface [LWN.net]
A "workqueue" is a list of tasks to perform, along with a (per-CPU) kernel thread to execute those tasks. Since a kernel thread is used, all tasks are run in process context and may safely sleep. Tasks running out of a special-purpose workqueue can sleep indefinitely, since they will not interfere ...
🌐
Infradead
infradead.org › ~mchehab › kernel_docs › core-api › workqueue.html
Concurrency Managed Workqueue (cmwq) — The Linux Kernel 5.10.0-rc1+ documentation
When there is no work item left on the workqueue the worker becomes idle. When a new work item gets queued, the worker begins executing again. In the original wq implementation, a multi threaded (MT) wq had one worker thread per CPU and a single threaded (ST) wq had one worker thread system-wide. A single MT wq needed to keep around the same number of workers as the number of CPUs. The kernel ...
🌐
Linux Kernel
kernel.org › doc › Documentation › core-api › workqueue.rst
========= Workqueue ========= :Date: September, 2010
There is no real advanage to the latter and an unbound workqueue provides a lot more flexibility. * Affinity scopes are introduced in Linux v6.5. To emulate the previous behavior, use strict "numa" affinity scope. * The loss of work-conservation in non-strict affinity scopes is likely originating from the scheduler. There is no theoretical reason why the kernel ...
🌐
GitHub
gist.github.com › yagihiro › 309746
workqueue sample on linux kernel · GitHub
Don't forget to cancel the possible work in the queue (cancel_delayed_work_sync) when you close the workqueue, otherwise your kernel will crash. ... You are a lifesaver, arxchruncher, I had spent an hour trying to figure out why my kernel crashed. ... Here is a minimal working example using cancel_work_sync https://github.com/cirosantilli/linux-kernel-module-cheat/blob/ad077d3943f79c0f6481dab929970613c33c31a7/kernel_module/workqueue_cheat.c
🌐
Kernel-internals
kernel-internals.org › interrupts › workqueues
Workqueues - Linux Kernel Internals
The kernel automatically manages a pool of worker threads. Each work item is queued and run when a worker becomes available. #include <linux/workqueue.h> /* Define a work item and its handler */ struct my_device { struct work_struct work; /* one-shot work */ struct delayed_work dwork; /* delayed ...
🌐
LWN.net
lwn.net › Articles › 731052
Power-efficient workqueues [LWN.net]
Workqueues (wq) are the most common deferred-execution mechanism used in the Linux kernel for cases where an asynchronous execution context is required. That context is provided by the worker kernel threads, which are woken whenever a work item is queued for them.
🌐
GitHub
gist.github.com › itrobotics › b4f5597585b74525e00e
a simple example of work_queue in Linux kernel · GitHub
a simple example of work_queue in Linux kernel · Raw · hello_tasklet.c · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters · Show hidden characters · Raw · hello_workqueue.c ·
🌐
Hitchhikersguidetolearning
hitchhikersguidetolearning.com › 2023 › 04 › 05 › workqueues-as-bottom-half-methods-in-the-linux-kernel
WorkQueues as bottom half methods in the Linux kernel | Hitch Hiker's Guide to Learning
Hence, in its most common form, a work queue is a simple interface for deferring work to a generic kernel thread. The workqueues run in process context and hence can sleep. In contrast Tasklets/SoftIRQ bottom half methods cannot sleep. There are two types of work defined in the Linux kernel ...
🌐
Linux Kernel
docs.huihoo.com › doxygen › linux › kernel › 3.7 › linux_2workqueue_8h.html
Linux Kernel: include/linux/workqueue.h File Reference
schedule_delayed_work_on - queue work in global workqueue on CPU after delay : cpu to use : job to be done : number of jiffies to wait · After waiting for a given time this puts a job in the kernel-global workqueue on the specified CPU.