通过简单的Linux字符设备驱动了解ioctl

本文介绍了如何在Linux内核模块中为file_operations结构体添加ioctl函数hello_ioctl,并详细展示了hello_ioctl的实现过程。通过定义幻数和ioctl命令,实现了设备文件的读写操作。此外,还提供了测试程序来验证ioctl功能的正确性,测试结果显示成功返回预期值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在hellow.c中(将来编译成一个内核模块插入到内核中工作),为file_operations中加入成员函数hello_ioctl:

/* file operations for hello device */
static struct file_operations hello_ops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = hello_ioctl,
    .open = hello_open,
    .read = hello_read,
    .write = hello_write,
    .release = hello_release,
};

hello_ioctl()的定义如下:

static int hello_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{    
    int temp = 0;
    switch(cmd)
    {
      case HELLO_CMD1:
           {    
              temp = 1;
              if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;
              break;
           }
      case HELLO_CMD2:
           {
              temp = 2;
              if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;
              break;
           }
    }
    printk( KERN_NOTICE"ioctl CMD%d done!\n",temp);   
    return 0;
}

 

   在文件开头增加cmd的定义:

#define HELLO_MAGIC 'k'
#define HELLO_CMD1    _IO(HELLO_MAGIC,0x1a)
#define HELLO_CMD2    _IO(HELLO_MAGIC,0x1b)

            其中'k'为幻数,要按照Linux内核的约定方法为驱动程序选择ioctl编号,应该首先看看include/asm/ioctl.h和Documentation/ioctl-number.txt这两个文件,下面是ioctl.h的部分内容,也是比较重要的:

注意对幻数的编号千万不能重复定义,如ioctl-number.txt已经说明‘k'的编号已经被占用的范围为:

'k'    00-0F    linux/spi/spidev.h    conflict!
'k'    00-05    video/kyro.h        conflict!

     所以我们在这里分别编号为0x1a和0x1b,到这里,我们已经完成了对ioctl功能的编写,接下来就是在测试程序中利用系统调用来测试它。

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

ioctl测试程序

=============================================================
#include <stdio.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define HELLO_MAGIC 'k'  //当然我们也可以定义一个相应的头文件,把ioctl的cmd放进里面,然后再include进 来
#define HELLO_CMD1    _IO(HELLO_MAGIC,0x1a)
#define HELLO_CMD2    _IO(HELLO_MAGIC,0x1b)

      int main(void)
{
    int ioctl_rdata;
    int fd, ret;

    fd = open ( "/dev/hellow" , O_RDWR);
    if ( fd == -1 )
    {
      perror("open");
      exit(0);
        }

    ret = ioctl( fd, HELLO_CMD2,&ioctl_rdata);
    if ( ret == -1)
    {
     perror("ioctl");
     exit(0);
    }
    printf("ioctl_rdata= %d \n",ioctl_rdata);

    close(fd);
    return 0;
}


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

运行结果

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

root@Ubuntu:~/share/hellow# insmod hellow.ko
root@Ubuntu:~/share/hellow# mknod /dev/hellow c 251 0
root@Ubuntu:~/share/hellow# ./a.out
ioctl_rdata= 2
root@Ubuntu:~/share/hellow# dmesg | tail

[ 2431.126532] hello init. major:251, minor:0
[ 2453.326022] Hello device open!

[ 2453.326047] ioctl CMD2 done!
[ 2453.326487] Hello device close!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值