書かれた他のキャラクタデバイスドライバ

書かれた他のキャラクタデバイスドライバ

Linux2.6カーネル、キャラクタデバイスCDEVの構成において、

次のようにCDEV構造(/リナックス/ cdev.h含む)が定義されます。

struct cdev {
    struct kobject kobj;               /* 内嵌的kobject对象 */
    struct module *owner;              /* 所属模块 */
    const struct file_operations *ops; /* 文件操作结构体 */
    struct list_head list;
    dev_t dev;                         /* 设备号 */
    unsigned int count;
};

構造体部材CDEV DEVは、デバイス番号、32ビット、12プライマリデバイス番号、デバイス番号20順位を定義します。

マクロは、DEVから、次のメジャー番号とマイナー番号を使用して得ることができ、そしてメジャー番号とマイナー番号によって生成されたdev_t、次のように定義されました:

#define MINORBITS   20
#define MINORMASK   ((1U << MINORBITS) - 1)

#define MAJOR(dev)  ((unsigned int) ((dev) >> MINORBITS)) /* 获取主设备号 */
#define MINOR(dev)  ((unsigned int) ((dev) & MINORMASK))  /* 获取次设备号 */
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))      /* 根据主次设备号生成dev*/

別の重要なメンバーfile_operationsのCDEV構造は、仮想ファイルシステムが利用可能なインタフェース機能キャラクタ・デバイス・ドライバを定義します。

Linux2.6カーネルは、次のように定義された動作CDEV構造のための関数のセットを提供します。

/* 用于初始化cdev的成员,并建立cdev和file_operation之间的连接 */
void cdev_init(struct cdev *, const struct file_operations *);
/* 用于动态申请一个cdev内存 */
struct cdev *cdev_alloc(void);
void cdev_put(struct cdev *p);
/* 向系统添加一个cdev,完成字符设备的注册 */
int cdev_add(struct cdev *, dev_t, unsigned);
/* 向系统删除一个cdev,完成字符设备的注销 */
void cdev_del(struct cdev *);

次の関数がシステムに最初に塗布装置番号と呼ばれるべきである前cdev_add()関数の呼び出しは、通常、システムにキャラクタデバイスドライバモジュールのロード機能、文字レジスタ装置で発生します。

/* 用于已知起始设备的设备号的情况 */
int register_chrdev_region(dev_t from, unsigned count, const char *name);
或者:
/* 用于设备号未知,向系统动态申请未被占用的设备号的情况 */
/* 调用该函数成功后,会把得到的设备号放入第一个参数dev中 */
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
            const char *name);

システムから文字装置の解除後cdev_del()関数のために、unregister_chrdev_region()は、元のアプリケーションのデバイス番号を解放するために呼び出されるべきです。

次のように具体的な用途は以下のとおりです。

/* 定义一个dev_t类型变量 */
dev_t dev_id;

static struct cdev xxx_cdev;
static int major;
static const struct file_operations xxx_fops = {
    .owner  = THIS_MODULE,
    .write  = xxx_write,
    .read   = xxx_read,
    .open   = xxx_open
};

/* 设备驱动模块加载函数 */
static int __init xxx_init(void)
{
    if (major) { /* 如果已知主设备号 */
        dev_id = MKDEV(major, 0);
        retval = register_chrdev_region(dev_id, 1, DEV_NAME);
    } else {
        retval = alloc_chrdev_region(&dev_id, 0, 1, DEV_NAME);
        major = MAJOR(dev_id);
    }
    cdev_init(&xxx_cdev, &xxx_fops);
    cdev_add(&xxx_cdev, dev_id, 1);
}

/* 设备驱动模块卸载函数 */
static void __exit xxx_exit(void)
{
    cdev_del(&xxx_cdev);
    unregister_chrdev_region(dev_id, 1);
}

おすすめ

転載: www.cnblogs.com/jasontian996/p/11519172.html