mcpField
W
writing-char-drivers

writing-char-drivers

github.com/mohitmishra786開発269299 回インストール18 週間前に更新
リポジトリ

writing-char-drivers について

Linux キャラクターデバイス実装を支援するエージェント向けスキルです。登録、ユーザー空間 I/O、ioctl、mmap、ポーリングの実用パターンと注意点を扱います。

主な機能

  1. 01キャラクターデバイスの登録
  2. 02安全なユーザー空間コピー
  3. 03ioctl コマンド設計
  4. 04デバイスメモリの mmap
  5. 05ポーリングと非同期 I/O

活用シーン

  1. 01/dev ノードを介したハードウェア公開
  2. 02カーネルの read、write、poll の実装
  3. 03型安全な ioctl インターフェースの設計
  4. 04検査を伴うデバイスメモリのマッピング

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill writing-char-drivers

インストール後、Claude Code で/writing-char-driversを入力して読み込まれたか確認します。

詳細

キャラクタードライバーの作成

目的

Linux のキャラクターデバイス実装について、エージェントをガイドします。struct file_operations、cdev の登録、安全なユーザー空間へのコピー、ioctl の設計、基本的な mmap を扱い、skills/kernel/device-drivers より踏み込んだ内容に焦点を当てます。

使用する場面

  • ハードウェアを /dev/mydev として公開する
  • カーネルから read/write/poll を実装する
  • 型安全なマクロを使って ioctl コマンドを定義する
  • デバイスの MMIO をユーザー空間にマッピングする(慎重に行ってください)

ワークフロー

1. キャラクターデバイスの登録
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

#define MY_MAJOR 0   /* 0 = dynamic alloc */
#define MY_MINOR 0

static dev_t devno;
static struct cdev my_cdev;
static struct class *class;

static const struct file_operations my_fops = {
    .owner          = THIS_MODULE,
    .open           = my_open,
    .release        = my_release,
    .read           = my_read,
    .write          = my_write,
    .unlocked_ioctl = my_ioctl,
    .llseek         = no_llseek,
};

static int __init my_init(void)
{
    int ret = alloc_chrdev_region(&devno, MY_MINOR, 1, "mydev");
    if (ret)
        return ret;

    cdev_init(&my_cdev, &my_fops);
    ret = cdev_add(&my_cdev, devno, 1);
    if (ret)
        goto err_cdev;

    class = class_create("mydev");
    device_create(class, NULL, devno, NULL, "mydev");
    return 0;

err_cdev:
    unregister_chrdev_region(devno, 1);
    return ret;
}

最近のドライバーでは、probe 内で devm_* バリアントを使うことがよくあります。

2. 安全なユーザー空間 I/O
static ssize_t my_read(struct file *filp, char __user *buf,
                       size_t count, loff_t *ppos)
{
    char kbuf[128];
    ssize_t len;

    if (*ppos >= sizeof(kbuf))
        return 0;
    len = min(count, sizeof(kbuf) - *ppos);
    memcpy(kbuf, "data", 4);
    if (copy_to_user(buf, kbuf + *ppos, len))
        return -EFAULT;
    *ppos += len;
    return len;
}

__user ポインターを直接参照しないでください。

3. ioctl のパターン
#include <linux/ioctl.h>

#define MY_IOC_MAGIC 'k'
#define MY_IOC_RESET  _IO(MY_IOC_MAGIC, 0)
#define MY_IOC_SET    _IOW(MY_IOC_MAGIC, 1, int)

static long my_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
    case MY_IOC_RESET:
        return 0;
    case MY_IOC_SET: {
        int val;
        if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
            return -EFAULT;
        return 0;
    }
    default:
        return -ENOTTY;
    }
}

固定サイズの構造体には _IOWR を使用してください。bi-arch では compat_ioctl を優先してください。

4. mmap(デバイスメモリ)
static int my_mmap(struct file *filp, struct vm_area_struct *vma)
{
    unsigned long size = vma->vm_end - vma->vm_start;
    phys_addr_t phys = device_phys_base;

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    return remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT,
                           size, vma->vm_page_prot);
}

明示的なサイズ制限と権限チェックを設けた場合に限り、DMA バッファーの mmap を優先してください。

5. poll/非同期 I/O

ブロッキング読み取りには poll と wake_up_interruptible を実装してください。SIGIO には fasync_helper を使用してください。

6. エージェントの使用方法
/writing-char-drivers Add unlocked_ioctl SET_SPEED to existing platform driver

よくある問題

症状原因対処法
-EFAULT不正なユーザーポインターaccess_ok(古いカーネルの場合)を検証するか、copy_* に任せる
ENOTTYioctl のマジック値が不一致ユーザー空間の ioctl.h に合わせる
メジャー番号の競合静的メジャー番号が使用済みalloc_chrdev_region を使用する
mmap で SIGSEGVデバイスへのキャッシュ済みマッピングpgprot_noncached
ioctl 内でスリープするスピンロックを保持しているブロックする前にロックを解除する

関連スキル

  • skills/kernel-dev/platform-device-model — probe のコンテキスト
  • skills/kernel/device-drivers — ドライバーのライフサイクル全体
  • skills/kernel/kernel-concurrency — file ops におけるロック
  • skills/kernel-dev/kernel-debugging-advanced — ioctl の経路をトレースする
  • skills/low-level-programming/linux-kernel-modules — モジュールのひな形

コメント