lsmod显示模块:
lsmod 以美观的方式列出/proc/modules的内容。
输出为:
Module(模块名) Size(模块大小) Used by(被...使用)
在/proc/modules中相应的是:
(模块名,模块大小,被...使用,模块地址
insmod:加载模块
rmmod:卸载模块
查看模块信息:
/proc/modules文件中列出了内核加载的所有模块的信息:
第一列:模块名称
第二列:模块使用的内存大小,单位是bytes
第三列:模块被load的次数
第四列:是否有其他模块依赖此模块,如果有,列出对应模块的名称
第五列:模块当前的状态,live(已经加载),loading(加载中),unloading(卸载中)
第六列:模块在内核内存中的偏移值
代码:
#include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> //#include <sys/types.h> //#include <errno.h> #include <linux/ioctl.h> // 这个头文件可能定义了 unlocked_ioctl 的类型
#define MY_IOCTL_CMD 0x99 #define MY_IOCTL_TYPE 0x99
static int Major; // 主设备号 static char msg[256]; // 存储消息的缓冲区 static char *msg_Ptr; // 当前写入的位置
void test(void) { return ; } EXPORT_SYMBOL(test);
static int hello_open(struct inode *inode, struct file *file) { test(); return 0; } static int hello_read(struct file *filp, char *buffer, size_t length, loff_t * offset) { int bytes_read = 0; if (*msg_Ptr == 0) return 0; // 如果没有数据可读,返回0 while (length && *msg_Ptr) { put_user(*(msg_Ptr++), buffer++); // 将数据复制到用户空间 length--; bytes_read++; } return bytes_read; } static int hello_write(struct file *filp, const char *buff, size_t len, loff_t * off) { int total_written = 0; while (len) { char c; get_user(c, buff); // 从用户空间读取数据 *(msg_Ptr++) = c; // 将数据写入到消息缓冲区中 len--; total_written++; buff++; } return total_written; }
static long hello_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { printk("hsm ioctl"); if (_IOC_TYPE(cmd) != 0x99) return -ENOTTY; else printk("ok......."); return 0; }
static int hello_release(struct inode *inode, struct file *file) { msg_Ptr = msg; // 重置消息指针到开始位置,以便下一次写入可以从开始位置开始 return 0; }
static struct file_operations hello_fops = { // .read = hello_read, // .write = hello_write, // .open = hello_open, // .release = hello_release, .unlocked_ioctl = hello_ioctl, };
static int hello_init(void) { Major = register_chrdev(0, "my_dev", &hello_fops); if (Major < 0) { printk(KERN_ALERT "Registering char device failed with %d\n", Major); return Major; } printk(KERN_INFO "I was assigned major number %d. To talk to the driver, create a dev file with 'mknod /dev/my_dev c %d 0'.\n", Major, Major); return 0; } static void hello_exit(void) { unregister_chrdev(Major, "my_dev"); printk(KERN_INFO "Unregistered and removed /dev/my_dev.\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
Makefile:
obj-m := driver.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build #KERNELDIR ?= /root/linux-4.19.90-all-arch-master PWD := $(shell pwd)
default: $(MAKE) -C ${KERNELDIR} M=$(PWD) modules clean: rm *.o *.ko *.symvers *.order *.mod.c .*.cmd .tmp_versions/ -rf
insmod后创建驱动文件,mknod /dev/my_dev c 237 0
应用:
#include <stdio.h> #include <unistd.h> #include <sys/ioctl.h> #include <fcntl.h>
#define MY_DEVICE_TYPE 0x99 #define MY_IOCTL_CMD _IOWR (MY_DEVICE_TYPE, 0x99, unsigned long)
int main() { int fd = open("/dev/my_dev", O_RDWR); // 替换为你的设备名 if (fd < 0) { perror("open"); return -1; } if (ioctl(fd, MY_IOCTL_CMD, "hello") < 0) { perror("ioctl"); close(fd); return -1; } printf("succ!\n"); close(fd); // 别忘了关闭文件描述符! return -1; }
Makefile:
OBJ=app
$(OBJ): app.c gcc app.c -o app
.PHONY:clean
clean: rm -rf app
测试:
调用成功。
dmesg:
使用dmesg显示内核打印日志:
这样简单的驱动驱动程序就实现了。。。。