1.目的
熟悉字符设备驱动程序编写及调试方法。
2.源码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/types.h>
#define SCULL_NAME "scull0"
struct st_scull_dev{
struct cdev char_dev;
};
static int scull_ioctl_open(struct inode *node,struct file *filep)
{
int ret = 0;
struct st_scull_dev *dev;
pr_info("%s device is open.\n", SCULL_NAME);
dev =container_of(node->i_cdev, struct st_scull_dev, char_dev);
filep->private_data= dev;
return ret;
}
static int scull_ioctl_release(struct inode *node,struct file *filep)
{
pr_info("%s device is close.\n", SCULL_NAME);
return 0;
}
static ssize_t scull_ioctl_read(struct file *filep, char __user *buffer, size_t count, loff_t *offp)
{
pr_info("sculldevice is read size: %ld. \n", count);
return 0;
}
static ssize_t scull_ioctl_write(struct file *filep, const char __user *buffer, size_t count, loff_t *offp)
{
ssize_t ret = (ssize_t)count;
pr_info("sculldevice is write size: %ld. \n", ret);
return ret;
}
static dev_t scull_dev_no;
static struct class *scull_class;
static struct st_scull_dev *scull_dev;
static const struct file_operations scull_fops = {
.owner= THIS_MODULE,
.read= scull_ioctl_read,
.write= scull_ioctl_write,
.open= scull_ioctl_open,
.release= scull_ioctl_release,
};
static int scull_init(void)
{
int ret = 0;
struct device *scull_device;
ret =alloc_chrdev_region(&scull_dev_no, 0, 1, SCULL_NAME);
if(ret < 0){
pr_err("%s:Error in allocating char device region. Err: %d\n", KBUILD_MODNAME, ret);
goto alloc_region_fail;
}
scull_class= class_create(THIS_MODULE, "scull_class");
if(IS_ERR(scull_class)){
pr_err("%s:Error in creating class\n", KBUILD_MODNAME);
ret= PTR_ERR(scull_class);
goto create_class_fail;
}
scull_device= device_create(scull_class, NULL, scull_dev_no, NULL, SCULL_NAME);
if(IS_ERR(scull_device)){
pr_err("%s:Error in creating character device.\n", KBUILD_MODNAME);
ret= PTR_ERR(scull_device);
goto create_device_fail;
}
scull_dev= kmalloc(sizeof(struct st_scull_dev), GFP_KERNEL);
if(!scull_dev){
pr_err("Errorallocating memory\n");
ret= -ENOMEM;
goto create_device_fail;
}
memset(scull_dev,0, sizeof(struct st_scull_dev));
cdev_init(&scull_dev->char_dev,&scull_fops);
ret =cdev_add(&scull_dev->char_dev, scull_dev_no, 1);
if(ret < 0){
pr_err("Errorin adding character device\n");
goto create_device_fail;
}
pr_info("%s major no: %d\n", SCULL_NAME, MAJOR(scull_dev_no));
return ret;
create_device_fail:
device_destroy(scull_class,scull_dev_no);
create_class_fail:
class_destroy(scull_class);
alloc_region_fail:
unregister_chrdev_region(scull_dev_no,1);
return ret;
}
static void scull_exit(void)
{
device_destroy(scull_class,scull_dev_no);
class_destroy(scull_class);
cdev_del(&scull_dev->char_dev);
unregister_chrdev_region(scull_dev_no,1);
kfree(scull_dev);
pr_info("Goodbye,cruel word\n");
}
module_init(scull_init);
module_exit(scull_exit);
MODULE_LICENSE("Dual BSD/GPL");
3.测试
sudo chmod 777 /dev/scull0 #修改字符设备权限
cat /dev/scull0 #读测试
ls -l > /dev/scull0 #写测试1
cp scull.c > /dev/scull0 #写测试2
cat /proc/devices #查看主设备号