linux 2.6核心 字元裝置驅動 相關函數

來源:互聯網
上載者:User
概述

本文介紹linux字元裝置註冊相關的四個函數:cdev_alloc、cdev_init、cdev_add和cdev_del。這四個函數在檔案:fs/char_dev.c中定義,在標頭檔include/linux/cdev.h中聲明。其中cdev_alloc和cdev_init是一對“互斥”函數,以不同的方式完成“相同”的功能:為函數cdev_add做前期準備。

cdev_alloc

504 /**
505  * cdev_alloc() - allocate a cdev structure
506  *
507  * Allocates and returns a cdev structure, or NULL on failure.
508  */
509 struct cdev *cdev_alloc(void)
510 {
511     struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
512     if (p) {
513         p->kobj.ktype = &ktype_cdev_dynamic;
514         INIT_LIST_HEAD(&p->list);
515         kobject_init(&p->kobj);
516     }
517     return p;
518 }

從函數名稱和第511行的代碼可以看出:這個函數動態申請結構體struct cdev,並對其進行初始化,最後將其指標返回。下面結合cdev_init進行進一步說明。

cdev_init

520 /**
521  * cdev_init() - initialize a cdev structure
522  * @cdev: the structure to initialize
523  * @fops: the file_operations for this device
524  *
525  * Initializes @cdev, remembering @fops, making it ready to add to the
526  * system with cdev_add().
527  */
528 void cdev_init(struct cdev *cdev, const struct file_operations *fops)
529 {
530     memset(cdev, 0, sizeof *cdev);
531     INIT_LIST_HEAD(&cdev->list);
532     cdev->kobj.ktype = &ktype_cdev_default;
533     kobject_init(&cdev->kobj);
534     cdev->ops = fops;
535 }

cdev_alloc和cdev_init的主要區別是:前者動態申請結構體struct cdev並對其進行初始化,後者將通過參數傳進來的結構體struct cdev進行初始化。

另一個主要區別是:cdev_alloc函數中沒有對struct cdev的ops域進行初始化,需要在cdev_alloc函數調用之後有專門的代碼對struct cdev的ops域進行初始化,而cdev_init函數中使用通過參數傳進來的struct file_operations結構體指標對struct cdev的ops域進行初始化,所以在函數cdev_init調用之後不需要再對struct cdev的ops域進行初始化。

cdev_add

447 /**
448  * cdev_add() - add a char device to the system
449  * @p: the cdev structure for the device
450  * @dev: the first device number for which this device is responsible
451  * @count: the number of consecutive minor numbers corresponding to this
452  *         device
453  *
454  * cdev_add() adds the device represented by @p to the system, making it
455  * live immediately.  A negative error code is returned on failure.
456  */
457 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
458 {
459     p->dev = dev;
460     p->count = count;
461     return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
462 }

函數cdev_alloc和cdev_init只是(申請)並初始化了(部分)結構體struct cdev,此時,struct cdev和核心還沒有任何關係。

函數cdev_add就是將函數cdev_alloc和cdev_init初始化後的struct cdev結構體註冊到核心中(第461行),自此核心就可以訪問裝置了。

cdev_del

本函數和函數cdev_add功能相反,從核心中刪除裝置。

 

給出代碼:

#include <linux/module.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#define MY_MAJOR 250

struct class *my_class;
struct cdev cdev;
dev_t dev;

int hello_open (struct inode *inode,struct file *filp)
{
    printk("#########  open  ######\n");
    return 0;
}

ssize_t hello_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
    printk("#########  read  ######\n");
    return count;
}

ssize_t hello_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
    printk ("#############  write  ############\n");
    return count;
}

int hello_release (struct inode *inode, struct file *filp)
{
    printk("#########  release  ######\n");
    return 0;
}

struct file_operations hello_fops ={
    .owner = THIS_MODULE,
    .open = hello_open,
    .read = hello_read,
    .write = hello_write,
    .release = hello_release,
};

int __init hello_init(void)
{
    int rc;
    dev = MKDEV(MY_MAJOR,0);
    printk ("Test hello dev\n");

    cdev_init(&cdev,&hello_fops);
    cdev.owner = THIS_MODULE;
    cdev.ops = &hello_fops;
    rc = cdev_add(&cdev,dev,1);
    if (rc < 0)
    {
        printk ("register %s char dev error\n","hello_dev");
        return -1;
    }
    my_class = class_create(THIS_MODULE,"hello_class");
    if(IS_ERR(my_class))
    {
        printk ("err:create class\n");
        return -1;
    }
    device_create(my_class, NULL, dev,NULL, "hello_dev");
    printk ("#############  init  ############\n");
    return 0;
}

void __exit hello_exit(void)
{
    cdev_del(&cdev);
    device_destroy(my_class,dev);
    class_destroy(my_class);
    printk("#############  exit  ############\n");
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.