Linux中驱动程序,可以像浏览器中的插件一样,通过模块插入方式与内核产生互动。
内核模块程序
hello.c
#include<linux/module.h>
#include<linux/kernel.h>
int __init myhello_init(void) {
printk("###############################\n");
printk("myhello is running\n");
printk("###############################\n");
return 0;
}
void __exit myhello_exit(void) {
printk("myhello will exit\n");
}
MODULE_LICENSE("GPL");
module_init(myhello_init);
module_exit(myhello_exit);
Makefile
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=(PWD) INSTALL_MOD_PATH=$(ROOTFS)
clean:
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers
else
obj-m += hello.o
endif
输出
[46328.986968] ###############################
[46328.986969] myhello is running
[46328.986970] ###############################
[46396.441806] myhello will exit
相关命令
sudo insmod ./???.ko #插件安装
lsmod #查看已经插入内核模块的插件
sudo rmmod #删除插件
sudo dmesg -C #清除插件输出信息
dmesg #查看插件输出信息printk
驱动程序
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
int major = 11;
int minor = 0;
int mychar_num = 1;
struct cdev mydev;
int mychar_open(struct inode *pnode, struct file *pfile) {
printk("mychar_open is called\n");
return 0;
}
int mychar_close(struct inode *pnode, struct file *pfile) {
printk("mychar_close is called\n");
return 0;
}
struct file_operations myops = {
.owner = THIS_MODULE,
.open = mychar_open,
.release = mychar_close,
};
int __init mychar_init(void) {
int ret = 0;
dev_t devno = MKDEV(major, minor);
// 申请设备号
ret = register_chrdev_region(devno, mychar_num, "mychar");
if (ret) {
ret = alloc_chrdev_region(&devno, minor, mychar_num, "mychar");
if (ret) {
printk("get devno failed\n");
return -1;
}
major = MAJOR(devno);
}
// 给struct cdev对象指定操作函数集
cdev_init(&mydev, &myops);
// 将struct cdev对象添加到内核对应的数据结构中
mydev.owner = THIS_MODULE;
cdev_add(&mydev, devno, mychar_num);
return 0;
}
void __exit mychar_exit(void) {
dev_t devno = MKDEV(major, minor);
cdev_del(&mydev);
unregister_chrdev_region(devno, mychar_num);
}
MODULE_LICENSE("GPL");
module_init(mychar_init);
module_exit(mychar_exit);
测试程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("The argument is too fewc\n");
return -1;
}
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
printf("open error\n");
return -1;
}
return 0;
}
安装驱动:sudo insmod mychar.ko
查看驱动主设备号:cat /proc/devices | grep mychar
创建驱动文件:sudo mknod /dev/mydev c 11 0
测试程序通过系统调用open函数,调用驱动程序,输出如下: