/***********************************************************************
*文件名称:cjf_chdev.c
*简要描述:本程序使用自旋锁对设备反问进行限制
*当前版本:3.0
*作者:Ceagle
*修改版本:1.0
***********************************************************************/ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/fs.h> #include <asm/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ceagle");
#define MAJOR_NUM 250 //定义主设备号为250,如果为0,表示内核动态分配设备号
#define DEVICE_NAME "cjf_chdev" //定义设备号的名称
#define DATA_NUM 20 //写入设备的字符串的最大长度
//声明打开设备函数
static int cjf_chdev_open(struct inode *inode,struct file *filp); //声明释放设备函数
static int cjf_chdev_release(struct inode *inode,struct file *filp); //声明读数据函数
static ssize_t cjf_chdev_read(struct file *filp,char *,size_t,loff_t *); //声明写数据函数
static ssize_t cjf_chdev_write(struct file *filp,char *,size_t,loff_t *);
//定义写入设备的字符串数组
static char cjf_chdev_var[DATA_NUM] ; static int cjf_chdev_count = 0; static spinlock_t spin = SPIN_LOCK_UNLOCKED;
static const struct file_operations cjf_chdev_fops = {
.open = cjf_chdev_open,
.release = cjf_chdev_release,
.read = cjf_chdev_read,
.write = cjf_chdev_write, };
int cjf_chdev_open (struct inode *inode,struct file *filp) {
spin_lock(&spin);//用于获得自旋锁,如果获得自旋锁spin则返回,否则继续等待
if (cjf_chdev_count) {
spin_unlock(&spin);
return -EBUSY;
}
cjf_chdev_count ++;
spin_unlock(&spin);
return 0; }
int cjf_chdev_release(struct inode *inode,struct file *filp) {
cjf_chdev_count --;
return 0; }
static ssize_t cjf_chdev_read(struct file *filp,char *buf,size_tcount,loff_t *f_pos) { //从内核拷贝数据到用户空间
if (copy_to_user(buf,&cjf_chdev_var,sizeof(cjf_chdev_var))) {
return -EFAULT;
}
return sizeof(cjf_chdev_var); } static ssize_t cjf_chdev_write(struct file *filp,char *buf,size_tcount,loff_t *f_pos) {
//从用户空间拷贝数据到内核空间
if (copy_from_user(&cjf_chdev_var,buf,sizeof(cjf_chdev_var))) {
return -EFAULT;
}
return sizeof(cjf_chdev_var); }
static int __init cjf_chdev_init(void) {
int reg;
//使用函数register_chrdev将主设备号和设备名注册到内核中,
//如果注册成功,返回0,否则返回负数;
//如果成功注册动态分配的设备,则返回设备号
reg = register_chrdev(MAJOR_NUM,DEVICE_NAME,&cjf_chdev_fops);
if (reg) {
printk("register fail!\n");
} else {
printk("register success!\n");
}
return reg; }
static void __exit cjf_chdev_exit(void) {
//使用register_chrdev将设备号和设备名从内核卸载
unregister_chrdev(MAJOR_NUM,DEVICE_NAME);
printk("chardev has been unregistered!\n"); }
module_init(cjf_chdev_init);
module_exit(cjf_chdev_exit);
|