Linux驱动程序设计.ppt - 百度文库 (baidu.com)
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内核模块,安装到内核时自动生成/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 测试程序