本文へ移動
cccskills
無料GitHub で公開

linux-kernel-modules

Use when writing loadable kernel modules: Kbuild, module parameters, proc and sysfs entries, char devices, or ftrace debugging. Not for driver architecture: use device-drivers.

インストール方法を見る

含まれるファイル(3)

  • SKILL.md8.8 KB
  • agents/openai.yaml201 B
  • references/kbuild-basics.md2.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Linux kernel modules

A loadable module runs in kernel space with no safety net. The build system, the userspace interfaces, and the debugging paths are all prescribed; follow them and the module stays debuggable.

Contract

FieldBound contract
TriggerThe task writes or builds an out-of-tree .ko, adds module parameters, creates proc or sysfs entries, registers a char device, debugs with KDB or ftrace, or signs modules for Secure Boot.
AuthorityReversible local: writes only the module source, Kbuild files, built artifacts, and local signing keys, plus load and unload of the module on this machine; rollback is rmmod for the loaded module and version control for the files. No remote mutation.
Side effectLocal build outputs, module insertion and removal, entries under /proc and /sys while loaded, and generated key material when signing is set up.
DoneThe module builds against the running kernel's build tree, loads, exposes its interfaces, and unloads without leaving state behind.

Inputs

  • The running kernel version and its build directory: required. uname -r and /lib/modules/$(uname -r)/build.
  • Root access: required for insmod, rmmod, and signing enrollment.
  • The module's userspace interface: required before writing code. Proc entry, sysfs attributes, or a char device.
  • For Secure Boot: the platform's key enrollment path.

Procedure

  1. Write the minimal module and build it through Kbuild. The Makefile is one line plus the invocation; Kbuild supplies every kernel flag. Done when: modinfo hello.ko prints the metadata and insmod plus rmmod round-trip cleanly.
#include <linux/module.h>
#include <linux/init.h>

static int __init hello_init(void) {
    pr_info("hello: loaded\n");
    return 0;                 // nonzero return aborts the load
}

static void __exit hello_exit(void) {
    pr_info("hello: unloaded\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Name");
MODULE_DESCRIPTION("Minimal loadable module");
obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD  := $(shell pwd)

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
make
sudo insmod hello.ko
lsmod | grep hello
sudo rmmod hello
dmesg | tail
  1. Add parameters for values that must change without a rebuild. The permission argument controls the sysfs visibility of each parameter. Done when: sudo insmod hello.ko count=3 applies the value and /sys/module/hello/parameters/count exists.
#include <linux/moduleparam.h>

static char *name = "world";
static int count = 1;
module_param(name, charp, S_IRUGO);
module_param(count, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(name, "Name to greet");
MODULE_PARM_DESC(count, "Number of times to greet");
  1. Create a proc entry when a reader needs formatted state. The seq_file callbacks fill one buffer per read; the file mode controls access. Done when: cat /proc/mymod prints the state.
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

static int mymod_show(struct seq_file *m, void *v) {
    seq_printf(m, "state: %d\n", my_state);
    return 0;
}

static int mymod_open(struct inode *inode, struct file *file) {
    return single_open(file, mymod_show, NULL);
}

static const struct proc_ops mymod_pops = {
    .proc_open    = mymod_open,
    .proc_read    = seq_read,
    .proc_lseek   = seq_lseek,
    .proc_release = single_release,
};

proc_create("mymod", 0444, NULL, &mymod_pops);
// remove_proc_entry("mymod", NULL); in module_exit
  1. Expose sysfs attributes for values that userspace reads and may write. sysfs_create_group attaches them under /sys/kernel/mymod/. Done when: read and write through the attribute round-trip the value.
#include <linux/kobject.h>
#include <linux/sysfs.h>

static struct kobject *mymod_kobj;
static int mymod_value;

static ssize_t value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
    return sysfs_emit(buf, "%d\n", mymod_value);
}
static ssize_t value_store(struct kobject *kobj, struct kobj_attribute *attr,
                           const char *buf, size_t count) {
    sscanf(buf, "%d", &mymod_value);
    return count;
}
static struct kobj_attribute value_attr = __ATTR(value, 0664, value_show, value_store);

mymod_kobj = kobject_create_and_add("mymod", kernel_kobj);
sysfs_create_group(mymod_kobj, &attr_group);   // check the return value
  1. Register a char device when userspace needs open, read, write on a node. A misc device gets a dynamic minor and creates /dev/mymod through udev without manual mknod. Done when: cat /dev/mymod reads data and the buffer bounds hold.
#include <linux/cdev.h>
#include <linux/uaccess.h>

#define BUF_SIZE 1024
static char dev_buf[BUF_SIZE];

static ssize_t mydev_read(struct file *f, char __user *buf, size_t len, loff_t *off) {
    size_t to_copy = min(len, (size_t)BUF_SIZE);
    if (copy_to_user(buf, dev_buf, to_copy))
        return -EFAULT;
    return to_copy;
}

static const struct file_operations mydev_fops = {
    .owner = THIS_MODULE,
    .read  = mydev_read,
};

static struct miscdevice mydev_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name  = "mymod",
    .fops  = &mydev_fops,
};
misc_register(&mydev_misc);      // check the return value
misc_deregister(&mydev_misc);    // in module_exit
  1. Debug with KDB and ftrace. KDB over serial or kgdboc gives a kernel debugger; ftrace traces function calls live and answers most timing questions without a debugger. Done when: the misbehaving call path or timing is captured.
# ftrace: trace the module's functions
echo 'mymod_*' > /sys/kernel/debug/tracing/set_ftrace_filter
echo function > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/trace
# and the quick printk path
echo 'file mymod.c +p' > /sys/kernel/debug/dynamic_debug/control
  1. Export symbols for other modules deliberately. EXPORT_SYMBOL shares with any module; EXPORT_SYMBOL_GPL restricts to GPL modules. Loading a module that imports GPL symbols without a GPL license taints the kernel and fails. Done when: modinfo shows the intended license and the import list matches it.
EXPORT_SYMBOL_GPL(my_shared_helper);
  1. Write KUnit tests for the module's pure logic. In-tree kernels build them with CONFIG_KUNIT; out-of-tree tests run as a KUnit module on a test kernel. Done when: the suite loads and reports its cases.
#include <kunit/test.h>

static void parse_valid(struct kunit *test) {
    KUNIT_EXPECT_EQ(test, mymod_parse("42"), 42);
}
static struct kunit_case mymod_cases[] = {
    KUNIT_CASE(parse_valid),
    {}
};
static struct kunit_suite mymod_suite = { .name = "mymod", .test_cases = mymod_cases };
kunit_test_suite(mymod_suite);
  1. Sign the module when Secure Boot is on. The kernel verifies module signatures against enrolled keys when CONFIG_MODULE_SIG is set, and a lockdown kernel rejects unsigned modules. Done when: modinfo hello.ko | grep signer shows the key and the module loads on the lockdown system.
openssl req -new -x509 -newkey rsa:4096 -keyout signing_key.pem \
        -out signing_cert.pem -nodes -days 36500 -subj "/CN=Module Signing"
scripts/sign-file sha256 signing_key.pem signing_cert.pem hello.ko
sudo mokutil --import signing_cert.pem    # enroll through MOK on UEFI, reboot to confirm

Failure and recovery

Failure classBehavior
Unknown symbol at insmodThe module imports a symbol nothing exports. Check the import list and the exporting module, and the license match for EXPORT_SYMBOL_GPL.
Invalid module formatThe module was built against a different kernel or architecture. Rebuild against uname -r's build tree.
Load leaves stale /proc or /sys stateThe exit path skipped cleanup. Make module_exit the mirror of module_init and reload.
Module hangs the boxReboot, then reproduce under ftrace with a filter narrowed to the module's functions before loading again.
Signature rejected on lockdownThe key is not enrolled, or the signature was invalidated by a rebuild. Re-sign after every rebuild and re-enroll once.
make cannot find the build treeThe kernel headers package is missing. Install the matching headers before building.

Output

The built and loadable module, its userspace interface verified by reads through /proc, /sys, or the device node, and clean unload evidence in dmesg. The Kbuild variable table and the out-of-tree versus in-tree comparison are in references/kbuild-basics.md. The mainline kernel this tree pins is 7.2 with LTS 6.18.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

af-xdp

無料

Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

agents-md

無料

Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

OutlineDriven のスキルをすべて見る

このスキルの問題を報告する