我正在尝试构建一个内核模块,但是在make文件中编译时我得到了一些我无法解决的错误。这是模块的代码:
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include "sar_main.h"
#define PROCFS_NAME "sarlkm"
char procfs_buffer[PROCFS_MAX_SIZE];
static unsigned long procfs_buffer_size = 0;
struct proc_dir_entry *proc_file_entry;
int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data){
int ret;
printk(KERN_INFO "procfile_read (/proc/%s) called \n", PROCFS_NAME);
if (offset > 0){
ret = 0;
}
else{
copy_to_user(procfs_buffer, buffer, procfs_buffer_size);
ret = procfs_buffer_size;
}
return ret;
}
int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data){
procfs_buffer_size = count;
if (procfs_buffer_size > PROCFS_MAX_SIZE){
procfs_buffer_size = PROCFS_MAX_SIZE;
}
if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size)){
return -EFAULT;
}
return procfs_buffer_size;
}
static const struct file_operations proc_file_ops = {
.read = procfile_read,
.write = procfile_write,
};
static int __init sar_init(void)
{
proc_file_entry = proc_create(PROCFS_NAME, 0644, NULL, &proc_file_ops);
if (proc_file_entry == NULL){
remove_proc_entry(PROCFS_NAME, NULL);
printk(KERN_ALERT "Error: Unable to create proc file");
return -ENOMEM;
}
printk(KERN_INFO "proc/%s successfully created", PROCFS_NAME);
return 0;
}
static void __exit sar_cleanup(void)
{
remove_proc_entry(PROCFS_NAME, NULL);
printk(KERN_INFO "proc/%s deleted", PROCFS_NAME);
}
module_init(sar_init);
module_exit(sar_cleanup);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
所以我在定义struct proc_file_ops时遇到错误。我还没有找到proc_dir_entry的读写函数的定义,但我在网上找到了一些使用了我所使用的完全相同的语句的例子。任何人都可以解释为什么我会收到这个警告以及该怎么办呢?
答案 0 :(得分:3)
您发现的示例可能适用于某些不同的内核版本(您使用的除外)。内部内核API因版本而异。看到 Documentation/stable_api_nonsense.txt了解详情。一般的建议是查看代码示例的内核源代码。例如,看看如何在kernel/time/timer_stats.c中实现proc API(当然在你的内核代码中)。
procfile_read()
和procfile_write()
函数的签名必须与struct file_operations
中的签名相同:
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
但你有下一个签名:
int procfile_read(char *buffer, char **buffer_location, off_t offset,
int buffer_length, int *eof, void *data)
int procfile_write(struct file *file, const char *buffer,
unsigned long count, void *data)
您可能需要仔细检查struct file_operations
中内核版本的实际签名。
另外,您可能会注意到需要设置.read
回调(在新的内核版本中):
.read = seq_read,
实际阅读应通过.open
回调:
.open = tstats_open,
在open函数中,你需要调用你的实际show函数,如下所示:
static int tstats_open(struct inode *inode, struct file *filp)
{
return single_open(filp, tstats_show, NULL);
}
show功能应该有这样的签名:
static int tstats_show(struct seq_file *m, void *v)
有关完整示例,请参阅内核中的kernel/time/timer_stats.c。