.h文件
#ifndef _DEMO_H_
#define _DEMO_H_
#include <linux/ioctl.h>
/*Macros to help debuging*/
#undef PDEBUG
#ifdef DEMO_DEBUG
#ifdef __KERNEL__
#define PDEBUG(fmt, args...) printk(KERN_DEBUG "DEMO:" fmt,## args)
#else
#define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
#endif
#else
#define PDEBUG(fmt, args...)
#endif
#define DEMO_MAJOR 224
#define DEMO_MINOR 0
#define COMMAND1 1
#define COMMAND2 2
struct demo_dev {
struct cdev cdev;
};
ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
loff_t demo_llseek(struct file *filp, loff_t off, int whence);
static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
#endif
.c文件
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/device.h>
#include "demo.h"
MODULE_AUTHOR("Gaowei");
MODULE_LICENSE("Dual BSD/GPL");
struct demo_dev *demo_devices;
static unsigned char demo_inc = 0;//全局变量,每次只能打开一个设备
static u8 demo_buffer[256];
static struct class *demo_class;
int demo_open(struct inode *inode, struct file *filp)
{
struct demo_dev *dev;
if (demo_inc > 0) return -ERESTARTSYS;
demo_inc++;
dev = container_of(inode->i_cdev, struct demo_dev, cdev);
filp->private_data = dev;
return 0;
}
int demo_release(struct inode *inode, struct file *filp)
{
demo_inc--;
return 0;
}
ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
int result;
loff_t pos = *f_pos; //pos: offset
if (pos >= 256) {
result = 0;
goto out;
}
if (count > (256 - pos))
count = 256 - pos;
pos += count;
if (copy_to_user(buf, demo_buffer+*f_pos, count)) {
count = -EFAULT;
goto out;
}
*f_pos = pos;
out:
return count;
}
ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
ssize_t retval = -ENOMEM;
loff_t pos = *f_pos;
if (pos > 256)
goto out;
if (count > (256 - pos))
count = 256 - pos;
pos += count;
if (copy_from_user(demo_buffer+*f_pos, buf, count)) {
retval = -EFAULT;
goto out;
}
*f_pos = pos;
retval = count;
out:
return retval;
}
static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
if (cmd == COMMAND1) {
printk("ioctl command 1 successfully\n");
return 0;
}
if (cmd == COMMAND2) {
printk("ioctl command 2 successfully\n");
return 0;
}
printk("ioctl error\n");
return -EFAULT;
}
loff_t demo_llseek(struct file *filp, loff_t off, int whence)
{
loff_t pos;
pos = filp->f_pos;
switch (whence) {
case 0:
pos = off;
break;
case 1:
pos += off;
break;
case 2:
default:
return -EINVAL;
}
if ((pos > 256) || (pos < 0))
return -EINVAL;
return filp->f_pos = pos;
}
struct file_operations demo_fops = {
.owner = THIS_MODULE,
.llseek = demo_llseek,
.read = demo_read,
.write = demo_write,
.unlocked_ioctl = demo_ioctl,
.open = demo_open,
.release = demo_release,
};
void demo_cleanup_module(void)
{
dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);
if (demo_devices) {
cdev_del(&demo_devices->cdev);
kfree(demo_devices);
}
unregister_chrdev_region(devno, 1);
}
/*Init module流程:
1)注册设备号MKDEV;
2)注册设备驱动程序,即初始化cdev结构(嵌入到demo_devices结构中)*/
int demo_init_module(void)
{
int result;
dev_t dev = 0;
dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);
result = register_chrdev_region(dev, 1, "DEMO");
if (result < 0) {
printk(KERN_WARNING "DEMO: can't get major %d\n", DEMO_MAJOR);
return result;
}
demo_devices = kmalloc(sizeof(struct demo_dev), GFP_KERNEL);
if (!demo_devices) {
result = -ENOMEM;
goto fail;
}
memset(demo_devices, 0, sizeof(struct demo_dev));
cdev_init(&demo_devices->cdev, &demo_fops);
demo_devices->cdev.owner = THIS_MODULE;
result = cdev_add(&demo_devices->cdev, dev, 1);
if (result) {
printk(KERN_NOTICE "error %d adding demo\n", result);
goto fail;
}
demo_class = class_create(THIS_MODULE, "DEMO");
device_create(demo_class, NULL, MKDEV(DEMO_MAJOR, DEMO_MINOR), NULL, "DEMO"); // create a device
return 0;
fail:
demo_cleanup_module();
return result;
}
module_init(demo_init_module);
module_exit(demo_cleanup_module);
Makefile文件
obj-m:=demo.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
原文链接: https://www.cnblogs.com/chaozhu/p/6245083.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/246963
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!