Linux驱动编写

Linux驱动程序设计.ppt - 百度文库 (baidu.com)

Hello World

lkm_example.c

 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/cdev.h>
 ​
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Keyon");
 MODULE_DESCRIPTION("A simple example Linux module.");
 MODULE_VERSION("0.01");
 ​
 static int __init lkm_example_init(void) {
  printk(KERN_INFO "Hello, World!\\n");
  return 0;
 }
 static void __exit lkm_example_exit(void) {
  printk(KERN_INFO "Goodbye, World!\\n");
 }
 module_init(lkm_example_init);
 module_exit(lkm_example_exit);

Makefile

 OBJ = lkm_example.o
 KO  = lkm_example.ko
 ​
 obj-m += $(OBJ)
 all:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 clean:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
 test:
     sudo dmesg -C
     sudo insmod $(KO)
     sudo rmmod $(KO)
     dmesg 

调用make编译内核模块

调用make test 测试装载内核模块与卸载内核模块

编写LED简易Linux内核控制模块实现

实现一个简易的Led内核模块,安装到内核时自动生成/dev/led设备节点

当用户空间open开/dev/led后,

调用ioctl(fd, 1, 3)时,内核模块可打印出"led_ioctl: LED_3 is TURN_ON;

调用ioctl(fd, 0, 4)时,内核模块可打印出"led_ioctl: LED_4 is TURN_OFF;

led_kernel.c

 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
  
 #define DEVICE_NAME "/dev/led_dev_yky"
 ​
 static struct cdev chr_dev;
 static dev_t ndev;
 ​
 static int chr_open(struct inode* inode, struct file* filp)
 {
     int major;
     int minor;
     
     major = MAJOR(inode->i_rdev);
     minor = MINOR(inode->i_rdev);
     
     printk("chr_open, major = %d, minor = %d\\n", major, minor);
     return 0;
 }
 ​
 static long chr_ioctl(struct file* filp, unsigned int cmd, unsigned long arg)
 {
     switch(arg)
     {
         case 3:
             if (cmd == 1) printk("led_ioctl: LED_3 is TURN_ON\\n");
             else printk("led_ioctl: LED_3 is TURN_OFF\\n");
             break;
         case 4:
             if (cmd == 1) printk("led_ioctl: LED_4 is TURN_ON\\n");
             else printk("led_ioctl: LED_4 is TURN_OFF\\n");
         default:
             return -EINVAL;
     }
     
     return 0;
 }
  
 static const struct file_operations chr_ops = 
 {
     .owner = THIS_MODULE,
     .unlocked_ioctl = chr_ioctl,
     .open = chr_open
 };
  
 static int demo_init(void)
 {
     int ret;
     
     cdev_init(&chr_dev, &chr_ops);
     ret = alloc_chrdev_region(&ndev, 0, 1, DEVICE_NAME);
     if(ret < 0 )
     {
         return ret;
     }
     
     printk("demo_init(): major = %d, minor = %d\\n", MAJOR(ndev), MINOR(ndev));
     ret = cdev_add(&chr_dev, ndev, 1);
     if(ret < 0)
     {
         return ret;
     }
     
     return 0;
 }
  
 static void demo_exit(void)
 {
     printk("demo_exit process!\\n");
     cdev_del(&chr_dev);
     unregister_chrdev_region(ndev, 1);
 }
  
 module_init(demo_init);
 module_exit(demo_exit);
  
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Keyon");
 MODULE_DESCRIPTION("A simple device example!");

Makefile

 NAME = led_kernel
 ​
 ifneq ($(KERNELRELEASE),)
 obj-m := $(NAME).o
  
 else
 PWD  := $(shell pwd)
 KVER := $(shell uname -r)
 KDIR := /lib/modules/$(KVER)/build
 all:
     $(MAKE) -C $(KDIR) M=$(PWD) modules
 clean:
     rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.*  Module.*
 install:
     sudo insmod $(NAME).ko
     dmesg | tail
     # sudo rm /dev/led_dev_yky 删除设备文件
     # sudo mknod /dev/led_dev_yky c 249 0 生成设备文件
 uninstall:
     sudo rmmod $(NAME).ko
 ​
 endif
 ​
 # dmesg | tail  查看内核打印内容
 ​

readTest.c 测试程序