添加设备自动注册
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/cdev.h>
static struct device *my_device;
static struct cdev my_cdev; // 字符设备结构
static struct class *my_class; // 设备类
static dev_t my_dev; // 设备号
static void *cma_area;
static dma_addr_t dma_handle;
static size_t size_of_cma = 4 * 1024; // CMA内存大小
#define MY_IOCTL_CMD _IOR('M', 1, dma_addr_t *)
static long my_driver_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case MY_IOCTL_CMD:
if (copy_to_user((dma_addr_t __user *)arg, &dma_handle, sizeof(dma_handle)))
return -EFAULT;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct file_operations my_driver_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = my_driver_ioctl,
// 其他file_operations成员...
};
static int __init my_driver_init(void)
{
int ret;
// 分配和注册设备号
ret = alloc_chrdev_region(&my_dev, 0, 1, "my_device");
if (ret < 0)
{
pr_err("Unable to allocate major number\n");
return ret;
}
// 创建设备类
my_class = class_create(THIS_MODULE, "my_class");
if (IS_ERR(my_class))
{
unregister_chrdev_region(my_dev, 1);
return PTR_ERR(my_class);
}
// 初始化字符设备
cdev_init(&my_cdev, &my_driver_fops);
my_cdev.owner = THIS_MODULE;
// 添加字符设备
ret = cdev_add(&my_cdev, my_dev, 1);
if (ret < 0)
{
class_destroy(my_class);
unregister_chrdev_region(my_dev, 1);
return ret;
}
// 创建设备节点
my_device = device_create(my_class, NULL, my_dev, NULL, "my_device");
if (IS_ERR(my_device))
{
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(my_dev, 1);
return PTR_ERR(my_device);
}
// 为设备申请CMA内存
cma_area = dma_alloc_coherent(my_device, size_of_cma, &dma_handle, GFP_KERNEL);
if (!cma_area)
{
pr_err("CMA memory allocation failed\n");
device_destroy(my_class, my_dev);
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(my_dev, 1);
return -ENOMEM;
}
char *tABC = (char *)cma_area;
tABC[0] = 'F';
tABC[1] = 'U';
tABC[2] = 'C';
tABC[3] = 'K';
pr_info("CMA Memory allocated. Physical Address = %pad\n", &dma_handle);
return 0;
}
static void __exit my_driver_exit(void)
{
if (cma_area)
{
dma_free_coherent(my_device, size_of_cma, cma_area, dma_handle);
}
device_destroy(my_class, my_dev);
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(my_dev, 1);
pr_info("CMA Memory and device freed\n");
}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple Linux driver for CMA memory allocation");
MODULE_VERSION("0.1");
最简版本
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
static struct device *my_device;
static void *cma_area;
static dma_addr_t dma_handle;
static size_t size_of_cma = 4*1024; // CMA内存大小,例如1KB
#define MY_IOCTL_CMD _IOR('M', 1, dma_addr_t *)
static long my_driver_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
switch (cmd) {
case MY_IOCTL_CMD:
if (copy_to_user((dma_addr_t __user *)arg, &dma_handle, sizeof(dma_handle)))
return -EFAULT;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct file_operations my_driver_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = my_driver_ioctl,
// 其他file_operations成员...
};
static int __init my_driver_init(void) {
int ret;
// 创建并注册设备
my_device = kzalloc(sizeof(*my_device), GFP_KERNEL);
if (!my_device) {
pr_err("Failed to allocate memory for device\n");
return -ENOMEM;
}
dev_set_name(my_device, "my_device");
ret = device_register(my_device);
if (ret) {
pr_err("Failed to register device\n");
kfree(my_device);
return ret;
}
// 为设备申请CMA内存
cma_area = dma_alloc_coherent(my_device, size_of_cma, &dma_handle, GFP_KERNEL);
if (!cma_area) {
pr_err("CMA memory allocation failed\n");
device_unregister(my_device);
kfree(my_device);
return -ENOMEM;
}
char* tABC = (char*)cma_area;
tABC[0] = 'F';
tABC[1] = 'U';
tABC[2] = 'C';
tABC[3] = 'K';
pr_info("CMA Memory allocated. Physical Address = %pad\n", &dma_handle);
return 0;
}
static void __exit my_driver_exit(void) {
dma_free_coherent(my_device, size_of_cma, cma_area, dma_handle);
device_unregister(my_device);
kfree(my_device);
pr_info("CMA Memory and device freed\n");
}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple Linux driver for CMA memory allocation");
MODULE_VERSION("0.1");
正文完