gpt4 book ai didi

linux - 如何在内核模块代码中添加轮询功能?

转载 作者:IT王子 更新时间:2023-10-28 23:58:41 25 4
gpt4 key购买 nike

据我所知,要从内核空间通知用户空间,一种方法是使用轮询。这意味着内核驱动程序应该首先提供 poll 方法。下面的代码是从网上找来的,确实有效!

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Fortune Cookie Kernel Module");
MODULE_AUTHOR("M. Tim Jones");

#define MAX_COOKIE_LENGTH PAGE_SIZE

static struct proc_dir_entry *proc_entry;
static char *cookie_buf; // Space for fortune strings
static int write_index; // Index to write next fortune
static int read_index; // Index to read next fortune

ssize_t fortune_write( struct file *filp, const char __user *buff,
unsigned long len, void *data )
// Refer to: ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
{
int space_available = (MAX_COOKIE_LENGTH-write_index);

if (len > space_available) {
printk(KERN_INFO "fortune: cookie buffer is full!\n");
return -ENOSPC;
}

if (copy_from_user( &cookie_buf[write_index], buff, len )) {
return -EFAULT;
}

write_index += len;
cookie_buf[write_index-1] = 0;

return len;
}

ssize_t fortune_read(struct file *file, char *buf, size_t count, loff_t *f_pos){
// Refer to: ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
int len;

//there's no fortune or a fortune has already been read
//the *f_pos > 0 hack is needed because `cat /proc/fortune` would otherwise
//display every thing in the cookie_buf
if(write_index == 0 || *f_pos > 0){
return 0;
}

// cicle through fortunes
if(read_index >= write_index){
read_index = 0;
}

len = sprintf(buf, "%s\n", &cookie_buf[read_index]);

read_index += len;
*f_pos += len;

return len;
}

static const struct file_operations proc_test_fops = {
.owner = THIS_MODULE,
// .open = led_proc_open,
.read = fortune_read,
// .llseek = seq_lseek,
// .release = single_release,
.write = fortune_write,
// unsigned int (*poll) (struct file *, struct poll_table_struct *);
// int (*fasync) (int, struct file *, int);
};

int __init init_fortune_module( void )
{
int ret = 0;
cookie_buf = (char *)vmalloc( MAX_COOKIE_LENGTH );
if (!cookie_buf) {
ret = -ENOMEM;
} else {
memset( cookie_buf, 0, MAX_COOKIE_LENGTH );
// proc_entry = create_proc_entry( "fortune", 0644, NULL );
proc_entry = proc_create( "fortune", 0644, NULL, &proc_test_fops );

if (proc_entry == NULL) {
ret = -ENOMEM;
vfree(cookie_buf);
printk(KERN_INFO "fortune: Couldn't create proc entry\n");
} else {
write_index = 0;
read_index = 0;
printk(KERN_INFO "fortune: Module loaded.\n");
}
}

return ret;
}

void __exit exit_fortune_module( void )
{
// remove_proc_entry("fortune", &proc_entry);
proc_remove(proc_entry);
vfree(cookie_buf);
printk(KERN_INFO "fortune: Module unloaded.\n");
}

module_init( init_fortune_module );
module_exit( exit_fortune_module );

我可以这样做让它工作:

echo "hello" > /proc/fortune

然后

cat /proc/fortune

查看结果。

但是如何给它添加poll方法呢?我尝试了几次,但还是失败了。

最佳答案

你可以在内核中找到一些很好的例子。查看下一个文件:

要将 poll() 函数添加到您的代码中,请按照以下步骤操作。

  1. 包括所需的 header :

     #include <linux/wait.h>
    #include <linux/poll.h>
  2. 声明等待队列变量:

     static DECLARE_WAIT_QUEUE_HEAD(fortune_wait);
  3. 添加 fortune_poll() 函数并将其(作为 .poll 回调)添加到您的文件操作结构中:

     static unsigned int fortune_poll(struct file *file, poll_table *wait)
    {
    poll_wait(file, &fortune_wait, wait);
    if (new-data-is-ready)
    return POLLIN | POLLRDNORM;
    return 0;
    }

    static const struct file_operations proc_test_fops = {
    ....
    .poll = fortune_poll,
    };

    请注意,您应该返回 POLLIN | POLLRDNORM 如果您有一些新数据要读取,0 如果没有新数据要读取(poll() 调用超时)。参见 man 2 poll了解详情。

  4. 一旦有新数据就通知您的等待队列:

     wake_up_interruptible(&fortune_wait);

这是实现 poll() 操作的基本内容。根据您的任务,您可能需要使用一些 waitqueue API在您的 .read 函数中(如 wait_event_interruptible())。


另见相关问题:Implementing poll in a Linux kernel module .

关于linux - 如何在内核模块代码中添加轮询功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30035776/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com