linux驱动开发从入门到rm -rf/】1 字符设备驱动20191225

家住魔仙堡 提交于 2019-12-26 05:55:46

老规矩,有人写的更好,不复制

 

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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!