添加字符设备ioctl

这篇博客介绍了如何在Linux 3.0内核上编写字符设备驱动,特别是如何添加ioctl功能。文章详细阐述了字符设备驱动的基本框架、初始化流程,并提供了代码示例,包括file_operations结构体的定义、open、read、write及ioctl函数的实现。通过hello_ioctl函数处理自定义的HELLO_CMD1和HELLO_CMD2命令,同时给出了测试ioctl功能的程序和运行结果。
摘要由CSDN通过智能技术生成

ioctl 中幻数使用 范围文件kernel\linux-3.0.y\Documentation\ioctl\ioctl-number.txt


功能:实现简单的字符操作(从用户空间向内核空间写入一串字符;从内核空间读一个字符到内核空间)
        众所周知,字符设备是linux下最基本,也是最常用到的设备,它是学习Linux驱动入门最好的选择,计算机的东西很多都是相通的,掌握了其中一块,其他就可以触类旁通了。在写驱动前,必须先搞清楚字符设备的框架大概是怎样的,弄清楚了流程,才开始动手,不要一开始就动手写代码!
        这里所说的框架是参考LLD3上介绍的,内核是基于Linux 2.6,3.0以上的有些地方会不一样(主要是file_operations中的ioctl修改了),但基本上适用,因为我就是在3.0的内核上实现的!字符设备驱动的初始化流程大概如下所示:

定义相关的设备文件结构体(如file_operation()中的相关成员函数的定义)->向内核申请主设备号(建议采用动态方式) ->申请成功后,调用MAJOR()获取主设备号 ->初始化cdev的结构体,调用cdev_init() ->调用cdev_add(),注册cdev到kernel ->注册设备模块:module_init()、module_exit()。

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

编写代码

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

            首先定义两个全局变量(主设备号和字符设备hellow):   

                                                           static int hello_major = 0;        /* major device number */

                                                           static struct cdev hellow;    /* hello device structure */

             然后来看看file_operations(),它的定义可以在../include/linux/fs.h下找到,这里只用到了其中的几个成员函数:

/* file operations for hello device */
static struct file_operations hello_ops = {
    .owner = THIS_MODULE,  /*owner为所有者字段,防止在使用时模块被卸载。一边都设为THIS_MODULE*/
    .open = hello_open,
    .read = hello_read,
    .write = hello_write,
    .release = hello_release,

};


       不同于windows驱动程序,Linux设备驱动程序在与硬件设备之间建立了标准的抽象接口。通过这个接口,用户可以像处理普通文件一样,通过open,close,read,write等系统调用对设备进行操作,如此一来也大大简化了linux驱动程序的开发。通过file_operations这个结构体(实际上是一个函数指针的集合),把驱动的操作和设备号联系起来,程序员所要做的工作只是通过file_operations挂接自己的系统调用函数。    

  

        接下来就是实现open,close,read,write操作了,这个驱动什么都没干,所以很好理解,用户请求read系统调用时,这个虚拟设备反回相应长度的“A”字符串,用户write时,将内容显示到日志中。这里要注意的是,内核空间中不能使用用户态的malloc,而是使用kmalloc/kfree。而且,用户read/write提供的buf地址也是用户态的,内核自然不能直接访问,需要通过copy_to_user/copy_from_user 进行数据拷贝,具体如下:

/* Open the device */
static int hello_open( struct inode *inode, struct file *filp ){
    printk( KERN_NOTICE"Hello device open!\n" );
    return 0;
}


/* Close hello_device */
static int hello_release( struct inode *inode, struct file *filp ){
    printk( KERN_NOTICE"Hello device close!\n" );
    return 0;
}


/* user read from hello device*/
ssize_t hello_read( struct file *flip, char __user *buf, size_t count,loff_t
                    *f_pos){
    ssize_t retval = 0;
    char *bank;
    bank = kmalloc(count+1, GFP_KERNEL );
    if( bank == NULL )
        return -1;
    memset( bank, 'A',count );
    if( copy_to_user( buf, bank, count ) ){
        retval = -EFAULT;
        goto out;
    }
    retval += count;
    *(bank+count)=0;
    printk( KERN_NOTICE"hello: user read %d bytes from me. %s\n",count,bank );
  out:
    kfree(bank);
    return retval;
}

/* write to hello device */
ssize_t hello_write( struct file *filp, const char __user *buf, size_t count,
                     loff_t *f_pos ){
    ssize_t retval = 0;
    char *bank = kmalloc( count ,GFP_KERNEL );
    if( bank == NULL )
        return retval;
    if( copy_from_user(bank, buf, count ) ){
        retval = -EFAULT;
        printk( KERN_NOTICE"hello: write error\

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值