字符驱动框架

Hello World

/*字符驱动框架*/
//*****************相关的头文件和宏定义*******************
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/version.h>
#define CLASS_NAME "char_cdev_class" /* 定义类名称 */
#define DEVICE_NAME "char_cdev" /* 定义设备名称 */
static int major = 232; /* 静态设备号方式的默认值 */
static int minor = 0; /* 静态设备号方式的默认值 */
static dev_t devno; /* 设备编号 */
static struct class *char_cdev_class;
module_param(major, int, S_IRUGO);
module_param(minor, int, S_IRUGO);
//*********** 文件操作接口函数定义 *********
398 static int char_cdev_open(struct inode *inode, struct file *filp)
{
// 打开设备操作
try_module_get(THIS_MODULE);
printk(KERN_INFO DEVICE_NAME " opened!\n");
return 0;
}
static int char_cdev_release(struct inode *inode, struct file *filp)
{
// 关闭设备操作
printk(KERN_INFO DEVICE_NAME " closed!\n");
module_put(THIS_MODULE);
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
static long char_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
// 设备 I/O 控制
printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
return 0;
}
#else
static int char_cdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
// 设备 I/O 控制
printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
return 0;
}
#endif
static ssize_t char_cdev_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
// 设备读操作
printk(KERN_INFO DEVICE_NAME " read method!\n");
return count;
}
static ssize_t char_cdev_write(struct file *filp, const char *buffer, size_t count, loff_t *ppos)
{
// 设备写操作
printk(KERN_INFO DEVICE_NAME " write method!\n");
399 return count;
}
//*********** fops 文件操作结构体 *********
static struct file_operations char_cdev_fops = {
.owner = THIS_MODULE,
.open = char_cdev_open,
.release = char_cdev_release,
.read = char_cdev_read,
.write = char_cdev_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
.unlocked_ioctl = char_cdev_ioctl,
#else
.ioctl = char_cdev_ioctl,
#endif
};
//**********设备驱动模块加载函数***********
static int char_cdev_init(void)
{
int ret;
/* 动态或静态申请设备号和注册设备 */
ret = register_chrdev(major, DEVICE_NAME, &char_cdev_fops);
if (major > 0) /* major=232,静态设备号 */
{
if (ret < 0) /* 申请、注册设备失败 */
{
printk(KERN_INFO " Can't get major number!\n");
return ret;
}
}
else /* major=0,动态设备号 */
{
printk(KERN_INFO " ret is %d\n", ret);
major = ret; /* 保存动态获取到的主设备号 */
}
devno = MKDEV(major, minor);
/* 在/sys/class/下创建 char_cdev_class 目录 */
char_cdev_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(char_cdev_class))
{
printk(KERN_INFO "create class error!\n");
return -1;
}
400
/* 将创建/dev/char_cdev 文件 */
device_create(char_cdev_class, NULL, devno, NULL, DEVICE_NAME);
printk(KERN_INFO "%s ok!\n", __func__);
return ret;
}
//**********设备驱动模块卸载函数***********
static void char_cdev_exit(void)
{
// 注销设备和释放设备号
device_destroy(char_cdev_class, devno);
class_destroy(char_cdev_class);
unregister_chrdev(major, DEVICE_NAME);
printk(KERN_INFO "%s\n", __func__);
}
module_init(char_cdev_init);
module_exit(char_cdev_exit);
//*********** 设备驱动许可证 ***********
MODULE_LICENSE("GPL");
posted @   zxz-FINE  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示