如何在内核模块代码中添加轮询功能? [英] How to add poll function to the kernel module code?

查看:120
本文介绍了如何在内核模块代码中添加轮询功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

,要从内核空间通知用户空间,一种方法是使用轮询.这意味着内核驱动程序应首先提供轮询方法. 下面的代码是从互联网上找到的,它确实有效!

as I know, to inform the user space from kernel space, one way is to using poll. That means kernel driver should provide poll method first. Below code is found from internet, and it really works!

#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

查看结果.

但是如何添加轮询方法呢?我试了几次,但还是失败了. 有人可以帮忙吗?谢谢!

But how to add poll method to it? I tried some times, but still failed. Could anyone help? Thanks!

推荐答案

您可以在内核本身中找到一些很好的示例.看看下一个文件:

You can find some good examples in kernel itself. Take a look at next files:

  • drivers/char/rtc.c
  • fs/proc/kmsg.c
  • drivers/char/random.c

要在代码中添加poll()函数,请执行以下步骤.

To add poll() function to your code follow next steps.

  1. 包括所需的标题:

  1. Include needed headers:

#include <linux/wait.h>
#include <linux/poll.h>

  • 声明等待队列变量:

  • Declare waitqueue variable:

    static DECLARE_WAIT_QUEUE_HEAD(fortune_wait);
    

  • 添加fortune_poll()函数并将其(作为.poll回调)添加到文件操作结构中:

  • Add fortune_poll() function and add it (as .poll callback) to your file operations structure:

    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民意调查.

    Note that you should return POLLIN | POLLRDNORM if you have some new data to read, and 0 in case there is no new data to read (poll() call timed-out). See man 2 poll for details.

    拥有新数据后通知您的等待队列:

    Notify your waitqueue once you have new data:

    wake_up_interruptible(&fortune_wait);
    

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

    That's the basic stuff about implementing poll() operation. Depending on your task, you may be needed to use some waitqueue API in your .read function (like wait_event_interruptible()).

    另请参阅相关问题:在Linux内核模块中实施民意调查.

    这篇关于如何在内核模块代码中添加轮询功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆