以下是一个简单的示例代码,实现了上述功能:
驱动程序:driver.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#define DEV_NAME "mydevice"
#define MEM_SIZE (8 * 1024 * 1024) // 8M Bytes
static dev_t dev;
static struct cdev my_cdev;
static struct class *my_class;
static struct proc_dir_entry *proc_entry;
// 内存缓冲区和全局变量定义
static char *mem_buffer;
static int buf_index = 0;
DEFINE_SPINLOCK(buf_lock);
DEFINE_MUTEX(io_mutex);
DECLARE_WAIT_QUEUE_HEAD(read_queue);
// 中断处理函数
irqreturn_t my_interrupt_handler(int irq, void *dev_id)
{
spin_lock(&buf_lock);
mem_buffer[buf_index++] = 'I';
spin_unlock(&buf_lock);
wake_up_interruptible(&read_queue);
return IRQ_HANDLED;
}
// 定时器回调函数
struct timer_list my_timer;
void my_timer_callback(unsigned long data)
{
spin_lock(&buf_lock);
mem_buffer[buf_index++] = 'T';
spin_unlock(&buf_lock);
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
}
// 字符设备接口实现
int my_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device opened.\n");
return 0;
}
int my_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device closed.\n");
return 0;
}
ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
int bytes_read = 0;
if (wait_event_interruptible(read_queue, buf_index > 0))
return -ERESTARTSYS;
spin_lock(&buf_lock);
while (count && buf_index > 0) {
put_user(mem_buffer[--buf_index], buf++);
count--;
bytes_read++;
}
spin_unlock(&buf_lock);
return bytes_read;
}
ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
int i;
mutex_lock(&io_mutex);
spin_lock(&buf_lock);
// 将用户写入的数据保存在全局缓冲区中
for (i = 0; i < count; i++) {
get_user(mem_buffer[buf_index++], buf + i);
}
spin_unlock(&buf_lock);
wake_up_interruptible(&read_queue);
mutex_unlock(&io_mutex);
return count;
}
long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case IOCTL_RESET:
spin_lock(&buf_lock);
buf_index = 0;
spin_unlock(&buf_lock);
break;
default:
return -ENOTTY;
}
return 0;
}
static unsigned int my_poll(struct file *filp, struct poll_table_struct *wait)
{
poll_wait(filp, &read_queue, wait);
if (buf_index > 0) {
return POLLIN | POLLRDNORM;
}
return 0;
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = my_open,
.release = my_release,
.read = my_read,
.write = my_write,
.unlocked_ioctl = my_ioctl,
.poll = my_poll,
};
// 初始化字符设备和中断
static int __init driver_init(void)
{
int ret;
unsigned long irqflags;
struct device *dev_ret;
// 分配设备号
if (alloc_chrdev_region(&dev, 0, 1, DEV_NAME) < 0) {
printk(KERN_ALERT "Failed to allocate char device region.\n");
return -1;
}
// 创建设备类
my_class = class_create(THIS_MODULE, DEV_NAME);
if (IS_ERR(my_class)) {
unregister_chrdev_region(dev, 1);
printk(KERN_ALERT "Failed to create device class.\n");
return PTR_ERR(my_class);
}
// 创建字符设备
cdev_init(&my_cdev, &my_fops);
ret = cdev_add(&my_cdev, dev, 1);
if (ret < 0) {
class_destroy(my_class);
unregister_chrdev_region(dev, 1);
printk(KERN_ALERT "Failed to add character device.\n");
return ret;
}
dev_ret = device_create(my_class, NULL, dev, NULL, DEV_NAME);
if (IS_ERR(dev_ret)) {
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(dev, 1);
printk(KERN_ALERT "Failed to create device.\n");
return PTR_ERR(dev_ret);
}
// 分配内存缓冲区
mem_buffer = kmalloc(MEM_SIZE, GFP_KERNEL);
if (!mem_buffer) {
device_destroy(my_class, dev);
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(dev, 1);
printk(KERN_ALERT "Failed to allocate memory buffer.\n");
return -ENOMEM;
}
// 创建 proc 文件系统入口
proc_entry = proc_create(DEV_NAME, 0666, NULL, &my_fops);
// 请求中断
irqflags = IRQF_TRIGGER_FALLING | IRQF_SHARED;
if (request_irq(IRQ_NUM, my_interrupt_handler, irqflags, DEV_NAME, NULL) < 0) {
kfree(mem_buffer);
device_destroy(my_class, dev);
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(dev, 1);
remove_proc_entry(DEV_NAME, NULL);
printk(KERN_ALERT "Failed to request interrupt.\n");
return -EIO;
}
// 初始化定时器
setup_timer(&my_timer, my_timer_callback, 0);
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
printk(KERN_INFO "Driver initialized.\n");
return 0;
}
static void __exit driver_exit(void)
{
del_timer_sync(&my_timer);
free_irq(IRQ_NUM, NULL);
remove_proc_entry(DEV_NAME, NULL);
kfree(mem_buffer);
device_destroy(my_class, dev);
cdev_del(&my_cdev);
class_destroy(my_class);
unregister_chrdev_region(dev, 1);
printk(KERN_INFO "Driver exited.\n");
}
module_init(driver_init);
module_exit(driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
用户态测试程序:test.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DEV_PATH "/dev/mydevice"
#define MEM_SIZE (8 * 1024 * 1024) // 8M Bytes
int main()
{
int fd;
char read_buf[MEM_SIZE];
char write_buf[] = "Hello, kernel!";
fd = open(DEV_PATH, O_RDWR);
if (fd < 0) {
perror("Failed to open device");
return -1;
}
// 向设备写入数据
if (write(fd, write_buf, sizeof(write_buf)) != sizeof(write_buf)) {
perror("Failed to write to device");
close(fd);
return -1;
}
// 从设备读取数据
if (read(fd, read_buf, sizeof(read_buf)) < 0) {
perror("Failed to read from device");
close(fd);
return -1;
}
printf("Read from device: %s\n", read_buf);
// 重置设备
if (ioctl(fd, IOCTL_RESET) < 0) {
perror("Failed to reset device");
close(fd);
return -1;
}
close(fd);
return 0;
}
请注意,上述代码只是一个简单示例,可能需要根据实际需求进行修改和适配。另外,代码中使用了一些宏和函数(例如 IOCTL_RESET
),这些需要自行定义或参考相关文档添加。
希望这个示例能够帮助到你!
内容由零声教学AI助手提供,问题来源于学员提问