A C kernel-programming project built around a bounded character device, rather than a collection of hello-world modules. The first driver exposes /dev/telecom_eventq through the misc-device API. It is a lab project, not a telecom packet driver or production kernel component.
- One global FIFO of 256 records shared by all file descriptors. Readers compete for records; this is not broadcast delivery.
- Write one native-endian unsigned 64-bit value. The driver adds a sequence number and monotonic timestamp.
- Read one 24-byte record: three native-endian 64-bit values (sequence, timestamp_ns, value). Reads smaller than a record return EINVAL; larger reads return one record. Writes must be exactly 8 bytes.
- Empty reads and full writes block, or return EAGAIN with O_NONBLOCK. Waits are interruptible.
poll()/epoll()readiness, bounded memory and backpressure; records are never silently overwritten.- Mutex-protected queue operations and copy-to-user failure handling that retains the queued record.
- Device permissions 0600. No real network traffic or process information is collected.
Use Linux with headers matching the target kernel:
make module
make userspace
make testmake module KDIR=/path/to/kernel/build supports a specific kernel build tree. Kernel module compatibility is tied to that kernel build, configuration and toolchain; this is not a portable binary module.
The following commands change the running kernel. Use a dedicated test VM with matching headers, not an employer or production machine. Load a fresh module with no other clients for the deterministic sequence assertions.
sudo insmod eventqueue.ko
sudo timeout 15s ./device_test
sudo rmmod eventqueueNormal module unloading is prevented while a file is open through .owner = THIS_MODULE. Do not force unload. Signing requirements depend on the test machine's configuration.
CI compiles the module against Ubuntu generic headers, compiles the device test and runs portable ring-buffer tests with sanitizers. CI does not load the module. The device test is provided for the VM workflow; runtime driver behaviour is not yet independently validated. Portable ring tests do not validate kernel synchronization or user-copy fault handling.
The developing host is Windows. Local checks cover the shared ring algorithm only; Linux compilation results come from CI. This distinction is deliberate.
The mutex makes ownership and failure semantics easy to review. Holding it during copy_to_user prevents another reader from consuming the same record and retains data on EFAULT, but a slow user page fault can stall other users. That is acceptable for a restricted lab device, not a claim of low latency.
An atomic depth value provides wait readiness hints. Every awakened operation rechecks the actual queue under the mutex; an atomic counter is not used as a substitute for queue synchronization. Sequence values wrap at 64 bits and reset on reload. Records are volatile and not durable.
Next: VM runtime CI, concurrent-reader/writer stress, signal interruption and user-copy fault tests, lockdep/KASAN/KCSAN runs, versioned ABI, per-open queues and measured contention. Keep each change tied to a reproducible failure or requirement before considering lock-free data structures.
For an interview, explain why a spinlock cannot surround a potentially sleeping user copy, why readiness must be rechecked, and why module reference counting matters. This project demonstrates kernel API practice; it does not replace evidence of professional kernel development.
Reference: Linux misc-device documentation.