単純な文字デバイスドライバ

ここでは単純な文字デバイスドライバがあります。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>


static unsigned int simple_dev_major_num = 222;

module_param(simple_dev_major_num, uint, S_IRUGO);

struct simple_cdev{
    struct cdev scdev;
    unsigned char data;
};

static struct simple_cdev *psimle_cdev = NULL;


int simple_cdev_open(struct inode *pinode, struct file *pfile)
{
    return 0;
}

int simple_cdev_close(struct inode *pinode, struct file *pfile)
{
    return 0;
}


static const struct file_operations simple_cdev_fopt = {
    .owner = THIS_MODULE,
    .open = simple_cdev_open,
    .release =simple_cdev_close,
};

static int __init simple_cdev_init(void)
{
    int ret;
    dev_t devno = MKDEV(simple_dev_major_num, 0);
    
    //申请/注册设备号
    if ( 0 == simple_dev_major_num )
    {
        ret = register_chrdev_region(devno, 1, "simple cdev");
    }
    else
    {
        ret = alloc_chrdev_region(&devno, 0, 1, "simple cdev");
        simple_dev_major_num = devno;
    }

    if ( ret < 0 )
    {
        printk(KERN_ERR "simple cdev get device num error\n");
        return ret;
    }
    
    psimle_cdev = kzalloc(sizeof(struct simple_cdev), GFP_KERNEL);
    if ( !psimle_cdev )
    {
        printk(KERN_ERR "simple cdev get memory failed\n");
        unregister_chrdev_region(devno, 1);
        return -ENOMEM;
    }
    
    //初始化字符设备
    cdev_init(&psimle_cdev->scdev, &simple_cdev_fopt);
    
    psimle_cdev->scdev.owner = THIS_MODULE;
    
    //添加设备
    ret = cdev_add(&psimle_cdev->scdev, devno,  1);
    if ( ret < 0 )
    {
        printk(KERN_ERR "add cdev failed\n");
        unregister_chrdev_region(devno, 1);
        return ret;

    }
    
    printk(KERN_INFO "simple cdev enter\n");
    return 0;
}
module_init(simple_cdev_init);

static void __exit simple_cdev_exit(void)
{
    printk(KERN_INFO "simple cdev exit\n ");
    if ( NULL != psimle_cdev )
    {
        cdev_del(&psimle_cdev->scdev);
        kfree(psimle_cdev);
    }
    unregister_chrdev_region(simple_dev_major_num, 1);
}
module_exit(simple_cdev_exit);

MODULE_AUTHOR("[email protected]");
MODULE_LICENSE("GPL v2");

いくつかの重要な構造を含みますstruct filestruct inodestruct cdevstruct file_operationsデバイスファイルのオープン、読み取り、書き込み、および実際のデバイスドライバに関連する他の動作のこれらのアプリケーション層の構造。次の図は、キャラクタデバイスドライバとファイルシステムとの関係を示したものです。

典型的には、デバイスの特定の文字は、次のように説明します。

struct simple_cdev{
    struct cdev scdev;
    unsigned char data;
    ...
    ...
};

構造体は、C ++で説明場合等価構造体simple_cdevは、ベース・クラスであるCDEV。

class cdev{
};

class simple_cdev::cdev{
    unsigned char data;
    ...
    ...
};

構造体は、操作のいくつかの重要な機能は、ファイルのlinux / FS / char_dev.cファイルに含まれているCDEV

int register_chrdev_region(dev_t from, unsigned count, const char *name);
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
            const char *name);
void unregister_chrdev_region(dev_t from, unsigned count);
void cdev_init(struct cdev *cdev, const struct file_operations *fops);
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
void cdev_del(struct cdev *p);

彼らは、使用の他のLKMのために、SYMBOL_EXPORTでシンボリックリンクをエクスポートします。

EXPORT_SYMBOL(register_chrdev_region);
EXPORT_SYMBOL(unregister_chrdev_region);
EXPORT_SYMBOL(alloc_chrdev_region);
EXPORT_SYMBOL(cdev_init);
EXPORT_SYMBOL(cdev_alloc);
EXPORT_SYMBOL(cdev_del);
EXPORT_SYMBOL(cdev_add);

最初の三つのx__chrdev_region機能は、アプリケーションとデバイス番号、関連する操作を解除する機能です。cdev_init構造体file_operations構造体CDEVデバイスドライバ内で定義は、関連付けられています。実際には、指定されたFOPSのためのOPS構造体CDEVの割り当てのメンバー。cdev_add, cdev_del/削除、システムの追加デバイスから/に、それは特定たkobject関連のデータ構造が一時的に組織化されたkobjectが分からないため、分析をしないでなければなりません。

struct cdev {
    struct kobject kobj;
    struct module *owner;
    const struct file_operations *ops;
    struct list_head list;
    dev_t dev;
    unsigned int count;
};

おすすめ

転載: www.cnblogs.com/thammer/p/12542652.html