Last active
December 16, 2015 08:59
-
-
Save creamidea/5410271 to your computer and use it in GitHub Desktop.
这是一个实例代码,当打开自己创建到设备打开时,读写时,调用自己写的内核模块函数。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/init.h> | |
#include <linux/kernel.h> | |
#include <linux/module.h> | |
#include <linux/moduleparam.h> /* Param header */ | |
#include <linux/fs.h> | |
/* | |
* register_chrdev_region(){} | |
* alloc_chrdev_region(){} | |
* unsregister_chrdev_region(){} | |
* */ | |
#include <linux/types.h> | |
/* | |
* dev_t | |
* MKDEV | |
* MAJOR, MINOR | |
* */ | |
#include <linux/cdev.h> | |
#include <linux/slab.h> | |
/* kfree(){} */ | |
#define DRIVER_AUTHOR "icecream <[email protected]>" | |
#define DRIVER_DESC "A sample driver" | |
#define MAJOR_NUM 200 /* 主设备号 */ | |
#define MINOR_NUM 0 /* 次设备号 */ | |
#define DEV_NAME "chardev" /* 设备名称 */ | |
/* 自己封装的结构体 */ | |
typedef struct { | |
struct cdev cdev; /* */ | |
} global_dev; | |
global_dev* global_devp = NULL; /* 全局的指针 */ | |
/* 读写操作 */ | |
/* inode描述节点,file描述的是系统中的 */ | |
static int chr_open(struct inode* inode, struct file* file) | |
{ | |
/* 先判断权限问题 */ | |
/* f_mode默认 全1 */ | |
if (file->f_mode & FMODE_READ) { | |
printk ("Open file Read Only\n"); | |
} else if (file->f_mode & FMODE_WRITE) { | |
printk ("Open file Write Only\n"); | |
} else { | |
printk ("read / write\n"); | |
} | |
/* 打开标志 */ | |
if (file->f_flags & O_NONBLOCK) { | |
printk ("NON Block\n"); | |
} else { | |
printk ("Block\n"); | |
} | |
return 0; | |
} | |
static int chr_close(struct inode* inode, struct file* file) | |
{ | |
printk ("Chr_close Close\n"); | |
return 0; | |
} | |
/* 实现file_operations结构体 */ | |
/* 上层和内核,中间桥梁作用 */ | |
static struct file_operations fops = { | |
.owner = THIS_MODULE, /* 指向当前指针模块 */ | |
.open = chr_open, | |
.release = chr_close /* close函数中只是简单的打印即可,系统会自动释放 */ | |
}; | |
static int major_num = 0; | |
/* 将设备添加到系统中去实现函数 */ | |
static void setup(global_dev* devp) | |
{ | |
/* 把当前添加到内核中正在使用的列表中,通过fops结构体 */ | |
cdev_init(&devp->cdev, &fops); | |
/* 动态配置 */ | |
devp->cdev.owner = THIS_MODULE; | |
devp->cdev.ops = &fops; | |
/* 设备,设备号,数量 */ | |
cdev_add(&devp->cdev, MKDEV(major_num, 0), 1); | |
/* 记得delete */ | |
} | |
static int __init openclose_init(void) | |
{ | |
int ret; | |
/* Makesure number of device */ | |
dev_t devno; /* 设备编号 */ | |
devno = MKDEV(MAJOR_NUM, MINOR_NUM); | |
/* register the devno to kernel */ | |
ret = register_chrdev_region(devno, 1, DEV_NAME); | |
if (ret < 0) { /* 主动注册失败 */ | |
/* 让系统帮忙注册 */ | |
/* 参数:设备号,次设备号,数量,设备名称 */ | |
alloc_chrdev_region(&devno, 0, 1, DEV_NAME); | |
} | |
major_num = MAJOR(devno); /* 提取主设备号,解决自动分配的设备号获取问题 */ | |
printk("major_num = %d\n", major_num); | |
/* 申请内存空间 */ | |
/* GFP_KERNEL will block(sleep)(阻塞),直到分配成功 */ | |
global_devp = (global_dev*)kmalloc(sizeof(global_dev), GFP_KERNEL); | |
if (global_devp == NULL) { | |
goto err; | |
} | |
/* global_devp 是全局,不传也可以 */ | |
setup(global_devp); | |
return 0; | |
err: | |
return -1; /* 告诉上层失败原因 */ | |
} | |
static void __exit openclose_exit(void) | |
{ | |
/* 删除设备,空间,释放空间 */ | |
cdev_del(&global_devp->cdev); | |
kfree(global_devp); | |
/* 注销设备 */ | |
/* 利用主次编号获取设备编号 */ | |
unregister_chrdev_region(MKDEV(major_num, 0), 1); | |
printk("unregister devno finished!\n"); | |
printk("Exit the driver module!\n"); | |
} | |
module_init(openclose_init); /* enter */ | |
module_exit(openclose_exit); /* out */ | |
MODULE_LICENSE("Dual BSD/GPL"); | |
MODULE_AUTHOR(DRIVER_AUTHOR); | |
MODULE_DESCRIPTION(DRIVER_DESC); | |
MODULE_ALIAS("Module Exercise"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment