LDD3-最简字符设备驱动freg (alloc_chrdev_region)

设备驱动分层:设备节点,设备驱动相关 用了半个月来看字符设备中的错综复杂的结构体,以后要达到的标准是从一个Hello World模板直接写出一个字符设备驱动程序

设备节点相关:

freg_init()

{

         err = alloc_chrdev_region(&dev, 0, 1 , FREG_DEVNODE_NAME);

         freg_major = MAJOR(dev);

         freg_minor = MINOR(dev);

          ..........

}

freg_exit()

{

         unregister_chrdev_region(MKDEV(freg_major, freg_minor), 0, 1 , FREG_DEVNODE_NAME);

          ..........

}

字符设备驱动层:

static struct file_operations freg_fops = {
        .owner = THIS_MODULE,
        .open = freg_open,
        .release = freg_release,
        .read = freg_read,
        .write = freg_write,
};


freg_init()

{

        cdev_init(&(dev->dev), &freg_fops);
        dev->dev.owner = THIS_MODULE;
        dev->dev.ops = &freg_fops;   //cdev_init会将freg_fops赋值给dev.ops所以不用再赋值 可以省略。


        err = cdev_add(&(dev->dev),devno, 1);

          ..........

}

freg_exit()

{

         cdev_del(&(freg_dev->dev));

          ..........

}

完整代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

static struct cdev *freg_cdev; //An instance of a character device
static dev_t ndev; //The node of the device

/* "freg"设备的全局变量 */
static int freg_var = 0;
//static int freg_major = 250;
static int freg_major = 0;
static int freg_minor = 0;

static ssize_t freg_read(struct file *filp, char __user *buf, size_t sz, loff_t *off)
{
	printk("In the freg_read() function!\n");
	/* 将freg_var从内核空间复制到用户空间 */
	if (copy_to_user(buf, &freg_var, sizeof(int))) {
		return - EFAULT;
	}
	printk("freg_read enter ,the data is %d\n",freg_var);
	return sizeof(int);
}

static ssize_t freg_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos)
{
	printk("In the freg_write() function!\n");
	/* 将用户空间的数据复制到内核空间的freg_var */
	if (copy_from_user(&freg_var, buf, sizeof(int))) {
		return -EFAULT;
	}
	printk("freg_write enter ,the data is %d\n",freg_var);
	return sizeof(int);
}

// file_operations is a very important data struct in character type device
struct file_operations freg_ops = {
		.owner = THIS_MODULE,
		.read = freg_read,
		.write = freg_write,
};

// initialization function of the module
static int __init freg_init(void)
{
	int err;

	printk(KERN_ALERT"Initializing freg device.\n");
// -----------------------设备号相关--------------------------
	err = alloc_chrdev_region(&ndev, 0, 1, "freg"); //allocate the device node number dynamically
	if(err < 0)
		return err;
	freg_major = MAJOR(ndev);
	freg_minor = MINOR(ndev);

	printk("freg_init():major=%d, minor=%d\n", MAJOR(ndev), MINOR(ndev));
// -------------------------完------------------------------

// ----------------------设备驱动相关--------------------------
	freg_cdev = cdev_alloc();

	cdev_init(freg_cdev, &freg_ops); //initialize the device instance

	freg_cdev->owner = THIS_MODULE;
	//freg_cdev->ops = &freg_ops;   //可以不做,因为cdev_init会将freg_ops赋值

	err = cdev_add(freg_cdev, ndev, 1);//register the char_dev into the system
	if(err < 0)
		return err;
// -------------------------完--------------------------------

	printk(KERN_ALERT"Succedded to initialize freg device.\n");

	return 0;
}

static void __exit freg_exit(void)
{
	ndev = MKDEV(freg_major, freg_minor);
	printk(KERN_ALERT"Destroy freg device.\n");
	cdev_del(freg_cdev); //unregister the char_dev from the system
	unregister_chrdev_region(ndev, 1);//free the device node number
}

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Fake Register Driver");

module_init(freg_init);
module_exit(freg_exit);




编译好后,insmod freg.ko加载驱动。

# cat /proc/devices | grep freg

通过以上命令来查找freg的主设备号

# mknod /dev/freg c 250 0

创建设备节点

应用程序测试:


测试结果:



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁保康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值