美文网首页
Linux 驱动开发2: IOCTL 操作

Linux 驱动开发2: IOCTL 操作

作者: wjundong | 来源:发表于2022-08-02 14:59 被阅读0次

IOCTL 示例

  • hello.c

    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    
    static int major = 0;
    
    static struct cdev mycdev;
    
    #define HELLO_IOC_MAGIC 'W'
    #define HELLO_IOC_NUMMAX 12
    
    #define HELLO_IOC_GET _IO(HELLO_IOC_MAGIC, 1)
    
    long hello_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
        int ret = 0;
    
        if(_IOC_TYPE(cmd) != HELLO_IOC_MAGIC) return -ENOTTY;
        if(_IOC_NR(cmd) >= HELLO_IOC_NUMMAX)  return -ENOTTY;
    
        switch (cmd)
        {
        case HELLO_IOC_GET:
            ret = __put_user(6666, (int __user *)arg);
            printk("HELLO_IOC_GET");
            break;
      
        default:
            break;
        }
      
        return ret;
    }
    
    static struct file_operations fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = hello_ioctl
    };
    
    static int hello_init(void)
    {
        int result;
        dev_t dev;
    
        /* 动态创建 */
        result = alloc_chrdev_region(&dev, 0, 1, "hello");
        major = MAJOR(dev);
    
        if(result < 0)
        {
            printk("register device error\n");
            return result;
        }
    
        printk("register device major %d\n", major);
    
        /* 添加字符设备 */
        cdev_init(&mycdev, &fops);
        mycdev.owner = THIS_MODULE;
        cdev_add(&mycdev, dev, 1);
    
        return 0;
    }
    
    static void hello_exit(void)
    {
        cdev_del(&mycdev);
        unregister_chrdev_region(MKDEV(major, 0), 1);
        printk("unregister device major %d\n", major);
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    
    MODULE_LICENSE("GPL");
    
  • Makefile

    KDIR ?= /lib/modules/$(shell uname -r)/build
    
    obj-m   := hello.o
    
    modules:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    clean:
        make -C $(KDIR) M=$(PWD) clean
    
  • test.c

    #include <stdio.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    
    #define HELLO_IOC_MAGIC 'W'
    #define HELLO_IOC_NUMMAX 12
    
    #define HELLO_IOC_GET _IO(HELLO_IOC_MAGIC, 1)
     
    int main(int argc, char** argv)
    {
      if(argc != 2) 
      {
          printf("usage: %s device (example /dev/hello) \n", argv[0]);
          return -1;
      }
        
      int fd = open(argv[1], O_RDONLY);
      if(fd < 0)
        {
          perror("failed to open device");
          return -1;
      }
    
      int num = 0;
      if(ioctl(fd, HELLO_IOC_GET, &num))
      {
          perror("failed to get num");
          return -1;
      }
    
        printf("get num %d\n", num);
        
      return 0;
    }
    
  • 运行

    $ make 
    $ gcc test.c
    $ sudo insmod 
    $ dmesg | tail
    # 获取主设备号
    $ sudo mknod /dev/hello c 244 0
    $ ./a.out /dev/hello
    get num 6666
    

相关文章

网友评论

      本文标题:Linux 驱动开发2: IOCTL 操作

      本文链接:https://www.haomeiwen.com/subject/bkaswrtx.html