常使用goto语句对错误进行处理回
错误码
IS_ERR(data)
会检查 data
是否是一个错误指针。如果是,PTR_ERR(data)
宏可以被用来将错误指针转换回原来的错误码(errno
值),以便进行进一步的错误处理;
需要包含头文件 errno.h
例:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/modulepram.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/asm-generic/uaccess.h>
#include <linux/errno.h>
static int major;
static int minor;
module_param(major,int,S_IRUGO);
MODULE_PARAM_DESC(major,"e.g:major=1");
module_param(minor,int,S_IRUGO);
MODULE_PARAM_DESC(minor,"e.g:minor=1");
static struct cdev cdev_test;
struct class *class;
struct device *device;
static int cdev_test_open(struct inode *node, struct file *file)
{
printk("cdev_test_open \n");
return 0;
}
static int cdev_test_release(struct inode *node, struct file *file)
{
printk("cdev_test_release \n");
return 0;
}
static ssize_t cdev_test_read (struct file *file, char __user *buf, size_t size, loff_t *off)
{
char kbuf[64]="123456hello";
copy_to_user(buf,kbuf,strlen(kbuf));
printk("cdev_test_read \n");
}
static ssize_t cdev_test_write (struct file *file, const char __user *buf, size_t size, loff_t *off)
{
char kbuf[64];
copy_from_user(kbuf,buf,size);
printk("write buf[%s]\n",kbuf);
printk("cdev_test_write\n");
}
struct file_operations cdev_test_ops={
.owner=THIS_MODULE,
.open=cdev_test_open,
.release=cdev_test_release,
.read=cdev_test_read,
.write=cdev_test_write,
.ioctl=cdev_test_ioctl
};
static int cdv_init(void)
{
dev_t dev_num;
int ret;
printk("input major=%d minor=%d \n",major,minor);
//动态申请
ret=alloc_chrdev_region(&dev_num,0,1,"chrdev_num");
if(ret <0 )
{
printk("alloc_chrdev_regionerr %d\n",ret);
goto err_alloc_chrdev_region ;
}
printk("dev_num=%d \n",dev_num);
major = MAJOR(dev_num);
minor = MINOR(dev_num);
printk("input major=%d minor=%d \n",major,minor);
cdev_test.owner= THIS_MODULE;
cdev_init(&cdev_test,&&cdev_test_ops);
ret = cdev_add(&cdev_test,dev_num,1);
if(ret <0 )
{
goto err_cdev_add ;
}
class = class_create(THIS_MODULE,"test");
if(IS_ERR(class))
{
ret=PTR_ERR(class);
goto err_class_create ;
}
device = device_create(class,NULL,dev_num,NULL,"/dev/test");
if(IS_ERR(device ))
{
ret=PTR_ERR( device );
goto err_device_create ;
}
printk("cdv init\n");
return 0;
err_device_create :
device_destroy(class,dev_num);
err_class_create :
classs_destroy(class);
err_cdev_add :
cdev_del(&cdev_test);
err_alloc_chrdev_region :
unregister_chrdev_region(dev_num,1);
return ret;
}
static void cdv_exit(void)
{
device_destroy(class,dev_num);
classs_destroy(class);
cdev_del(&cdev_test);
//释放设备号
unregister_chrdev_region(dev_num,1);
printk("cdv exit\n");
return 0;
}
module_init(cdv_init);
module_exit(cdv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SONG");
MODULE_VERSION("v1.0");