Linux内核删除driver,Linux Kernel Driver 分离模型示例

类型定义

// hello_def.h

#ifndef __HELLO_DEF_H__

#define__HELLO_DEF_H__

#define HELLO_OPEN (0X10001001U)

#define HELLO_CLOSE (0X10001002U)

#define HELLO_INFO (0X10001003U)

// 声明描述 hello 硬件相关的数据结构(自定义硬件信息)

struct hello_resource

{

int phys_addr; // 寄存器的物理地址

int size; // 寄存器的内存大小

int pin; // 管脚编号

};

#endif // __HELLO_DEF_H__

硬件部分

// hello_dev.c

#include #include #include #include "hello_def.h"

// 定义hello的硬件信息

// 此为对应的硬件的固有信息

static struct hello_resource hello_info = {

.phys_addr = 0xE0200000,

.size = 8,

.pin = 3

};

static void hello_release(struct device *dev)

{

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

}

// 定义初始化硬件节点

static struct platform_device hello_dev = {

.name = "hello", // 用于匹配

.id = -1,

.dev = {

.platform_data = &hello_info, // 装载自定义的硬件信息

.release = hello_release // 避免内核警告

}

};

static int __init hello_dev_init(void)

{

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

// 注册硬件节点到dev链表,内核进行遍历和匹配

platform_device_register(&hello_dev);

return 0;

}

static void __exit hello_dev_exit(void)

{

// 删除节点

platform_device_unregister(&hello_dev);

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

}

module_init(hello_dev_init);

module_exit(hello_dev_exit);

MODULE_LICENSE("GPL");

软件部分

// hello_drv.c

#include #include #include #include #include #include #include "hello_def.h"

static struct hello_resource hello_info;

static long hello_unlocked_ioctl(struct file * f, unsigned int cmd, unsigned long arg)

{

switch (cmd)

{

case HELLO_OPEN:

{

printk("===[frocheng]===[%s]===[%s]===[open]===\n",__FILE__, __func__);

}

break;

case HELLO_CLOSE:

{

printk("===[frocheng]===[%s]===[%s]===[close]===\n",__FILE__, __func__);

}

break;

case HELLO_INFO:

{

// info 命令,我们将我们的固有的硬件信息,返回给用户空间

printk("===[frocheng]===[%s]===[%s]===[info]===\n",__FILE__, __func__);

copy_to_user((void*)arg, &hello_info, sizeof(hello_info));

}

break;

default:

{

printk("===[frocheng]===[%s]===[%s]===[Unkown Command]===\n",__FILE__, __func__);

}

return -1;

}

return 0;

}

// 定义初始化hello的硬件操作对象

static struct file_operations hello_fops =

{

.owner = THIS_MODULE,

.unlocked_ioctl = hello_unlocked_ioctl

};

static const char name[] = "hello";

// 定义初始化混杂设备对象

static struct miscdevice hello_misc =

{

.minor = MISC_DYNAMIC_MINOR,

.name = name,

.fops = &hello_fops

};

// pdev指向匹配成功的硬件节点(hello_dev.c的hello_dev)

static int hello_probe(struct platform_device *pdev)

{

struct hello_resource *pdata;

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

pdata = pdev->dev.platform_data;

// 获取 硬件信息,进行处理,此处进行打印展示处理

printk("=[frocheng]=[%s]=[%s]=[0X%X]=[%d]=[%d]=\n",

__FILE__, __func__, pdata->phys_addr, pdata->size, pdata->pin);

hello_info.phys_addr = pdata->phys_addr;

hello_info.pin = pdata->pin;

hello_info.size = pdata->size;

misc_register(&hello_misc); // 注册

return 0;

}

// pdev指向匹配成功的硬件节点(hello_dev.c的hello_dev)

static int hello_remove(struct platform_device *pdev)

{

misc_deregister(&hello_misc); // 卸载

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

return 0;

}

// 定义初始化软件节点

static struct platform_driver hello_drv = {

.driver = {

.name = "hello" // 用于匹配

},

.probe = hello_probe, // 匹配成功调用

.remove = hello_remove // 卸载软件或者硬件调用

};

static int __init hello_drv_init(void)

{

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

// 注册硬件节点到drv链表,内核进行遍历和匹配

platform_driver_register(&hello_drv);

return 0;

}

static void __exit hello_drv_exit(void)

{

// 删除节点

platform_driver_unregister(&hello_drv);

printk("=[frocheng]=[%s]=[%s]=\n", __FILE__, __func__);

}

module_init(hello_drv_init);

module_exit(hello_drv_exit);

MODULE_LICENSE("GPL");

测试代码

// test.c

#include #include #include #include #include #include #include #define HELLO_OPEN (0X10001001UL)

#define HELLO_CLOSE (0X10001002UL)

#define HELLO_INFO (0X10001003UL)

struct dev_info

{

int pysy;

int size;

int pin;

};

int main()

{

int fd = open("/dev/hello", O_RDWR);

if (fd < 0)

{

perror("open");

return 0;

}

do

{

int ret = 0;

ret = ioctl(fd, HELLO_OPEN);

if (ret != 0)

{

perror("ioctl");

break;

}

printf("open success!\n");

sleep(1);

ret = ioctl(fd, HELLO_CLOSE);

if (ret != 0)

{

perror("ioctl");

break;

}

printf("close success!\n");

sleep(1);

struct dev_info info;

ret = ioctl(fd, HELLO_INFO, &info);

if (ret != 0)

{

perror("ioctl");

break;

}

printf("info success, 0X%X, %d, %d!\n",info.pysy, info.size, info.pin);

ret = ioctl(fd, 234);

if (ret != 0)

{

perror("ioctl");

printf("Other command error!\n");

break;

}

} while(0);

close(fd);

return 0;

}

编译

测试程序

(不要跟驱动代码放到一个目录下)

gcc -g tets.c -o ioctl_test

驱动

Makefile

KERNDIR:= /lib/modules/`uname -r`/build/

PWD:= $(shell pwd)

obj-m+= hello_dev.o

obj-m+= hello_drv.o

all:

make -C $(KERNDIR) M=$(PWD) modules

clean:

make -C $(KERNDIR) M=$(PWD) clean

测试

1. sudo insmod hello_dev.ko

2. sudo insmod hello_drv.o

3. sudo ./test

4. sudo rmmod hello_drv

5. sudo rmmod hello_dev

结果

f383998b44f4e2d63565ce6c040cc116.png

65f6e3e2eb59db36a52944e540f2e1ea.png

上面两个红色框中,其实是我这把 ioctrl_test应用程序运行了两次。如果运行一次,红色框中几条日志就只会打印一遍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值