老规矩,有人写的更好,不复制
https://blog.csdn.net/ARAFATms/article/details/79397800
照办。但是注意:安装驱动、运行测试程序
都要sudo 用管理员权限运行,不然肯定出错
我的测试:ubuntu18.04lts
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/fs.h"
#include "linux/init.h"
#include "linux/types.h"
#include "linux/errno.h"
#include "linux/uaccess.h"
#include "linux/kdev_t.h"
#define MAX_SIZE 1024
MODULE_AUTHOR("Downey"); //作者信息
MODULE_DESCRIPTION("Linux kernel driver - hello_world PLUS!"); //模块的描述,可以使用modinfo xxx.ko指令来查看
MODULE_VERSION("0.1"); //模块版本号
//指定license版本
MODULE_LICENSE("GPL"); //设置加载时可传入的参数
int my_open(struct inode *inode, struct file *file);
int my_release(struct inode *inode, struct file *file);
ssize_t my_read(struct file *file, char __user *user, size_t t, loff_t *f);
ssize_t my_write(struct file *file, const char __user *user, size_t t, loff_t *f);
char message[MAX_SIZE] = "this is shuaiboy's Drive"; //打开设备时会显示的消息
int device_num;//设备号
char* devName = "myCharDevice";//设备名
struct file_operations pStruct =
{
open:my_open,
release:my_release,
read:my_read,
write:my_write,
};
//设置初始化入口函数
static int __init hello_world_init(void)
{
int ret;
ret = register_chrdev(0, devName, &pStruct);
if (ret < 0)
{
printk("failed to register %s\n", devName);
return -1;
}
else
{
printk("%s has been registered!\n", devName);
printk("id: %d\n", ret);
device_num = ret;
return 0;
}
}
//设置出口函数
static void __exit hello_world_exit(void)
{
unregister_chrdev(device_num, devName);
printk("unregister %s successful.\n", devName);
}
//将上述定义的init()和exit()函数定义为模块入口/出口函数
module_init(hello_world_init);
module_exit(hello_world_exit);
//打开
int my_open(struct inode *inode, struct file *file)
{
printk("open lgsDrive OK!\n");
try_module_get(THIS_MODULE);
return 0;
}
//关闭
int my_release(struct inode *inode, struct file *file)
{
printk("Device released!\n");
module_put(THIS_MODULE);
return 0;
}
//读设备里的信息
ssize_t my_read(struct file *file, char __user *user, size_t t, loff_t *f)
{
if(copy_to_user(user,message,sizeof(message)))
{
return -2;
}
return sizeof(message);
}
//向设备里写信息
ssize_t my_write(struct file *file, const char __user *user, size_t t, loff_t *f)
{
if(copy_from_user(message,user,sizeof(message)))
{
return -3;
}
return sizeof(message);
}
makefile
obj-m := myCharDevice.o #这里是上面所创建的c文件名.o
PWD := $(shell pwd)
KERNELDIR := /lib/modules/$(shell uname -r)/build/ #你要安装mod的内核版本
all:
make -C $(KERNELDIR) M=$(PWD) modules
.PHONY: clean
clean:
rm -rf *.o *~ core *.ko *.mod.c modules.order Module.symvers
linux下的测试程序,直接 gcc test_myCharDevice.c 就编译了
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_SIZE 1024
int main(void)
{
int fd;
char buf[MAX_SIZE]; //缓冲区
char get[MAX_SIZE]; //要写入的信息
char *dir = "/dev/myCharDevice"; //设备名
fd = open(dir, O_RDWR | O_NONBLOCK);
if (fd != -1)
{
//读初始信息
read(fd, buf, sizeof(buf));
printf("%s\n", buf);
//写信息
printf("input :");
gets(get);
write(fd, get, sizeof(get));
//读刚才写的信息
read(fd, buf, sizeof(buf));
printf("device Message: %s\n", buf);
close(fd);
return 0;
}
else
{
printf("Device open failed\n");
return -1;
}
}
用过的命令
tail -f /var/log/kern.log
另开一个terminal
sudo insmod myCharDevice.ko
sudo mknod /dev/myCharDevice c 240 0
ll /dev
gcc test_myCharDevice.c
sudo ./a.out
sudo rm /dev/myCharDevice
sudo rmmod myCharDevice
来源:CSDN
作者:观海ao
链接:https://blog.csdn.net/liaofeifly/article/details/103703965