register_chrdev和register_chrdev_region

使用register_chrdev注册字符设备

注册字符设备可以使用register_chrdev函数。
int register_chrdev (unsigned int major, const  char *name, struct file_operations*fops); 
register_chrdev函数的major参数如果等于0,则表示采用系统动态分配的主设备号。



注销字符设备可以使用unregister_chrdev函数。
int unregister_chrdev(unsigned int major, const char *name); 

例1.3  register_chrdev注册字符设备实例
核心代码如下所示:
static unsigned char simple_inc=0;  
static unsigned char demoBuffer[256];  
int simple_open(struct inode *inode, struct file *filp)  
{  
    if(simple_inc>0)return -ERESTARTSYS;  
    simple_inc++;  
    return 0;  
}  
int simple_release(struct inode *inode, struct file *filp)  
{  
    simple_inc--;  
    return 0;  
}  
ssize_t simple_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)  
{  
    /* 把数据复制到应用程序空间 */  
    if (copy_to_user(buf,demoBuffer,count))  
    {  
       count=-EFAULT;   
    }  
    return count;  
}  
ssize_t simple_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)  
{  
    /* 把数据复制到内核空间 */  
    if (copy_from_user(demoBuffer+*f_pos, buf, count))  
    {  
        count = -EFAULT;  
    }  
    return count;  
}  
struct file_operations simple_fops = {  
    .owner =    THIS_MODULE,  
    .read =     simple_read,  
    .write =    simple_write,  
    .open =     simple_open,  
    .release =  simple_release,  
};  
/*******************************************************  
                MODULE ROUTINE  
*******************************************************/  
void simple_cleanup_module(void)  
{  
    unregister_chrdev(simple_MAJOR,  "simple");   
    printk("simple_cleanup_module!\n");  
}  
int simple_init_module(void)  
{  
    int ret;  
    //根据设备号与设备名注册字符设备  
    ret = register_chrdev(simple_MAJOR, "simple", &simple_fops);   
    if (ret < 0)  
    {  
        printk("Unable to register character device %d!\n",simple_MAJOR);  
        return ret;  
    }  
    return 0;  
}  
module_init(simple_init_module);  
module_exit(simple_cleanup_module);  
应用程序的代码如下:
void main(void)  
{  
    int fd;  
    int i;  
    char data[256];  
    int retval;  
    fd=open("/dev/fgj",O_RDWR);  
    if(fd==-1)  
    {  
        perror("error open\n");  
        exit(-1);  
    }  
    printf("open /dev/fgj successfully\n");  
    //写数据  
    retval=write(fd,"fgj",3);  
    if(retval==-1)  
    {  
        perror("write error\n");  
        exit(-1);  
    }  
    //读数据  
    retval=read(fd,data,3);  
    if(retval==-1)  
    {  
        perror("read error\n");  
        exit(-1);  
    }  
    data[retval]=0;  
    printf("read successfully:%s\n",data);  
    //关闭设备  
    close(fd);  
}  
字符设备模块使用insmod加载,加载完毕需要在/dev目录下使用mkmod命令建立相应的文件结点,编译生成的应用层可执行程序为test。本例运行结果如下:
[root@/home]#insmod demo.ko  
[root@urbetter /home]# mknod /dev/fgj c 224 0  
[root@urbetter /home]# ./test   
open /dev/fgj successfully  
read successfully:fgj 

====================================================================================================================================

 int register_chrdev(unsigned int major, const char *name, struct file_operations *fops); 
其中,major是为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态地分配一个主设备号。name是设备名。fops就是前面所说的对各个调用的入口点的说明。此函数返回0表示成功。返回-EINVAL表示申请的主设备号非法,一般来说是主设备号大于系统所允许的最大设备号。返回-EBUSY表示所申请的主设备号正在被其它设备驱动程序使用。如果是动态分配主设备号成功,此函数将返回所分配的主设备号。如果register_chrdev操作成功,设备名就会出现在/proc/devices文件里。在成功的向系统注册了设备驱动程序后(调用register_chrdev()成功后),就可以用mknod命令来把设备映射为一个特别文件,其它程序使用这个设备的时候,只要对此特别文件进行操作就行了。

====================================================================================================================================


分配设备编号,注册设备与注销设备的函数均在fs.h中声明,如下:
extern int register_chrdev_region(dev_t,unsigned int,const char*);表示静态的申请和注册设备号
extern int alloc_chrdev_region(dev_t,unsigned int,const char*);表示动态的申请和注册设备号
extern int register_chrdev(unsigned int,const char*,struct file_operations*);表示int为0时动态注册,非零静态注册。

在linux2.6版本里面,register_chrdev_region是register_chrdev的升级版。
使用register_chrdev_region函数时,首先要定义一个dev_t变量来作为一个设备号,dev_t dev_num;如果想静态申请,那么
dev_num=MKDEV(major_no,0);major_no表示设备号的变量,然后便可以使用register_chrdev_region(dev_num,2,"my_dev");第二个参数表示注册的设备数量,第三个表示驱动名
如果要动态的注册设备号,使用下面alloc_chrdev_region(&dev_num,0,2,"memdev");次设备号从0开始,注册两个设备,设备名为memdev。
前面只是注册了设备号,后面要向内核添加设备了;
struct cdev devno;
cdev_init(&devno,&file_operations) // 初始化设备
devno.owner=THIS_MODULE;
devno.ops=&mem_fops
对于已经知道了主设备号,就用cdev_add(&devno,dev_num,MEMDEV_NR_DEVS);来添加设备
如果是动态申请的设备号,就用cdev_add(&devno,MKDEV(mem_major,0),MEMDEV_NR_DEVS);

由此可见,使用register_chrdev_region()比register_chrdev()多了一步,就是想内核注册添加cdev设备的步骤。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值