美文网首页
Linux 驱动开发1: 模块化驱动

Linux 驱动开发1: 模块化驱动

作者: wjundong | 来源:发表于2022-07-27 20:11 被阅读0次

    最简单的模块

    • hello.c

      #include <linux/module.h>
      
      int hello_init(void)
      {
          printk("Hello module init\n");
          return 0;
      }
      
      void hello_exit(void)
      {
          printk("Hello module exit\n");
      }
      
      module_init(hello_init);
      module_exit(hello_exit);
      
      MODULE_LICENSE("GPL");
      
    • Makefile

      KDIR ?= /lib/modules/`uname -r`/build
      
      obj-m += hello.o
      
      module:
          make -C $(KDIR) M=$(PWD) modules
      
      clean:
          make -C $(KDIR) M=$(PWD) clean
      
    • 运行

      $ make
      
      $ sudo insmod hello.ko
      $ lsmod | grep hello
      $ cat /proc/modules | grep hello
      
      $ sudo rmmod hello
      $ dmesg | tail
      

    获取主设备号

    • hello.c

      #include <linux/module.h>
      #include <linux/fs.h>
      
      /* 设置主设备号, 0 则由系统创建 */
      static int major = 0;
      
      static int hello_init(void)
      {
          int result;
          dev_t dev = MKDEV(major, 0);
      
          /* 配置主设备号 */
          if(major)
              result = register_chrdev_region(dev, 1, "hello");
          else        
          {
              /* major 为 0 则动态创建 */
              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);
      
          return 0;
      }
      
      static void hello_exit(void)
      {
          dev_t dev = MKDEV(major, 0);
      
          unregister_chrdev_region(dev, 1);
      
          printk("unregister device major %d\n", major);
      }
      
      module_init(hello_init);
      module_exit(hello_exit);
      
      MODULE_LICENSE("GPL");
      
    • 运行

      $ make 
      $ sudo insmod hello.ko
      $ dmesg | tail 
      $ cat  /proc/devices | grep hello
      
      $ sudo rmmod hello
      $ dmesg | tail 
      $ cat  /proc/devices | grep hello
      

    添加字符设备

    • hello.c

      #include <linux/module.h>
      #include <linux/fs.h>
      #include <linux/cdev.h>
      
      /* 填入希望绑定的主设备号, 0 则由系统决定 */
      static int major = 0;
      
      static struct cdev mycdev;
      
      #define MIN(a, b) (((a) < (b)) ? (a) : (b))
      
      static int hello_open(struct inode *node, struct file *file)
      {
          printk("open hello module\n");
      
          return 0;
      }
      
      static ssize_t hello_read(struct file *file, char __user *buf, size_t size, loff_t *ofs)
      {
          int n, m;
          char say[] = "Hello World\n";
          
          if(*ofs >= sizeof(say))
              return 0;
          
          m = MIN(sizeof(say) - *ofs, size);
      
          n = copy_to_user(buf, say + *ofs, m);
          *ofs += m - n;
          
          return m - n;
      }
      
      static struct file_operations fops = {
          .owner = THIS_MODULE,
          .open = hello_open,
          .read = hello_read,
      };
      
      static int hello_init(void)
      {
          int result;
          dev_t dev = MKDEV(major, 0);
      
          /* 配置主设备号 */
          if(major)
              result = register_chrdev_region(dev, 1, "hello");
          else        
          {
              /* major 为 0 则动态创建 */
              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");
      
    • 运行

      
      $ make 
      $ sudo insmod hello.ko
      $ cat  /proc/devices | grep hello
      # 填入获取的主设备号, 这里是 511
      $ sudo mknod /dev/hello c 511 0
      $ cat /dev/hello
      Hello World
      

    相关文章

      网友评论

          本文标题:Linux 驱动开发1: 模块化驱动

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