Hello,World驱动之旅,对外接口(二)

目录

(一)上篇回顾:上一篇讲到如何加载自己的hello驱动模块。Hello,World驱动之旅,初识驱动模块(一)-CSDN博客

(二)驱动模块的意义是什么?

(三)hello模块升级,常见class属性文件

(四)添加属性文件功能

(五)完整代码如下:


(一)上篇回顾:上一篇讲到如何加载自己的hello驱动模块。Hello,World驱动之旅,初识驱动模块(一)-CSDN博客

  1. 我们通过指令insmod加载hello.ko
  2. module_init对应的函数会被执行调用。
  3. 通过dmesg查看内核LOG,发现hello_init中“hello, world!”有打印
  4. 通过rmmod卸载hello驱动模块
  5. 通过dmesg查看内核LOG,发现hello_exit中“see you agin”有打印

(二)驱动模块的意义是什么?

我们的hello驱动莫i狂,仅仅打印一行Log吗?当然不是,虽然目前仅打印了一行Log,不过这已经很厉害了,这个已经是跟内核打交道了,我们的模块已经是操作系统的一员了。所以我们继续努力,丰富我们的Hello模块,让他具备更多的功能。

总所周知,Linux的设计哲学中,有一条核心原则:一切皆文件。这一原则意味着在Linux中,几乎所有的资源和设备都以文件的形式进行表示和访问,我们的hello驱动模块当然也不例外,我们需要为我们的hello模块打开对外服务的大门,通过文件节点的方式提供,这样上层应用才能访问到我们的驱动服务,否则我们的hello模块毫无意义。抛开具体字符设备、块设备、网络设备不谈,我们先通过其他简单方式打开该通过。

(三)hello模块升级,常见class属性文件

通过class_create创建struct class类,"cdevhelloclass"文件讲被创建,位于/sys/class目录下

hellodev.chardev_class = class_create(THIS_MODULE,"cdevhelloclass");

进入Ubuntu命令行,加载模块,执行ls命令,查看/sys/class目录,已生成cdevhelloclass。

通过class_create_file创建class类的属性文件

ret = class_create_file(hellodev.chardev_class, &class_attr_test);

进入Ubuntu命令行,加载模块,执行ls命令,查看/sys/class/cdevhelloclass目录,已生成test文件

(四)添加属性文件功能

class_create_file提供了属性文件的读写方法,可以通过读/写实现与应用的沟通作用,我们再store方法中对全局变量做了+1操作,在show方法中对全局变量进行了显示操作,也就是每写一次文件,我们再进行读取操作,我们将能获取到该文件节点总的写入次数。

static ssize_t test_show(struct class *class, struct class_attribute *attr,
                        char *buf)
{
	int len;
    len = sprintf(buf,"test write count:%d\n",hellodev.count);
	printk("%s\n",buf);
    return len;                           
}

 static ssize_t test_store(struct class *class, struct class_attribute *attr,
                        const char *buf, size_t count)
{ 
	hellodev.count++;
    return count;
}

static CLASS_ATTR_RW(test);

在读写测试我们之前,我们先要修改下文件的读写权限sudo chmod 666 test,再执行ls -la,查看属性已切换至rw-rw-rw(原文件属性为644,即rw-r--r--),这样我们普通用户也有了对该文件的读写操作,否则只能以root用户身份执行该操作。

最后,我们通过我们尝试通过命令echo以及cat对test文件进行读写测试,如下:

至此,大功告成,外界已经可以通过echo以及cat与我们驱动程序进行通信了,我们已经搭建了最基础的内核与应用之间沟通的桥梁。

(五)完整代码如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>

#define MEMORY_SIZE 4096

struct hello_cdev
{
	struct class *chardev_class;
	char *buf;
	int count;
};

static struct hello_cdev hellodev;


static ssize_t test_show(struct class *class, struct class_attribute *attr,
                        char *buf)
{
	int len;
    len = sprintf(buf,"test write count:%d\n",hellodev.count);
	printk("%s\n",buf);
    return len;                           
}

 static ssize_t test_store(struct class *class, struct class_attribute *attr,
                        const char *buf, size_t count)
{ 
	hellodev.count++;
    return count;
}

static CLASS_ATTR_RW(test);

					

static int hello_init(void)
{
	int ret;
	hellodev.count = 0;
	hellodev.buf = (char *)vmalloc(MEMORY_SIZE);
	if(hellodev.buf == NULL ){
		goto error;
	}
	memset(hellodev.buf,0x00,MEMORY_SIZE);
	sprintf(hellodev.buf,"test write count:%d",hellodev.count);
	hellodev.chardev_class = class_create(THIS_MODULE,"cdevhelloclass");
	if(IS_ERR(hellodev.chardev_class))
	{
		printk("Err: failed in creating class.\n");
		goto calss_error;
	}

	ret = class_create_file(hellodev.chardev_class, &class_attr_test);
    if (ret) {
        printk("could not create sysfs files\n"); 
		goto class_file_error;
    }

    printk("hello, world!\r\n");
    return 0;
class_file_error:
	class_destroy(hellodev.chardev_class);		
calss_error:
	vfree(hellodev.buf);		
error:
	return -1;
		
}
 
static void hello_exit(void)
{	
	class_remove_file(hellodev.chardev_class, &class_attr_test);
	class_destroy(hellodev.chardev_class);/*	删除类 */
	vfree(hellodev.buf);
	
    printk("see you agin\r\n");
}
 
module_init(hello_init);
module_exit(hello_exit);
 
MODULE_LICENSE("GPL");		//MODULE_LICENSE
MODULE_AUTHOR("DriverDesigner"); //声明作者信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值