前情提要:
移植代码的时候遇到create_proc_read_entry函数,新的内核里已经没有这个函数了,只能找对应的替换。
proc_create_data函数就是可以替换掉它,本文主要讲解下如何使用proc_create_data,以及相关的参数配置。
proc_create_data函数
函数定义在“linux/proc_fs.h”头文件中
extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
struct proc_dir_entry *,
const struct file_operations *,
void *);
对应的实现在“fs/proc/generic.c”文件中
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
struct proc_dir_entry *parent,
const struct file_operations *proc_fops,
void *data)
{
struct proc_dir_entry *pde;
if ((mode & S_IFMT) == 0)
mode |= S_IFREG;
if (!S_ISREG(mode)) {
WARN_ON(1); /* use proc_mkdir() */
return NULL;
}
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO;
pde = __proc_create(&parent, name, mode, 1);
if (!pde)
goto out;
pde->proc_fops = proc_fops;
pde->data = data;
if (proc_register(parent, pde) < 0)
goto out_free;
return pde;
out_free:
kfree(pde);
out:
return NULL;
}
EXPORT_SYMBOL(proc_create_data);
proc_create_data的参数解析:
- const char *name: //name为传递想要创建的/proc下的文件名
- umode_t mode: //mode为建立的文件所拥有的读写等权限
- struct proc_dir_entry *parent: //parent为你要在哪个文件夹下建立名字为name的文件,如:init_net.proc_net是要在/proc/net/下建立文件
- const struct file_operations *proc_fops: //proc_fops为struct file_operations *指针(重点)
- void *data //data保存似有数据的指针,如不要为NULL
其中比较重要的是proc_fops参数,对应的是一连串的file_operations,不需要全部填满,根据需求写,给个参考:
static const struct file_operations lm75_proc_fops = {
.open = lm75_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
对应的只需要将open实现一下,其他的都可以照搬
static int lm75_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, lm75_proc_show, NULL);
}
lm75_proc_open函数内的lm75_proc_show再去写对应的具体操作,就可以替换掉老版本的create_proc_read_entry了。
完整实例
放一个完整版的,如何在代码中添加proc_create_data函数,做一个参考:
/*create_proc_read_entry isn't existed in the later 3.10.0*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
static int lm75_read_proc(char *buf, char **start, off_t off,
int count, int *eof, void *data)
{
u32 dev_id = (u32)data;
...
return len;
}
#else
static int lm75_proc_show(struct seq_file *seq, void *v)
{
u32 dev_id = (u32)((uintptr_t) seq->private);
...
return 0;
}
static int lm75_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, lm75_proc_show, NULL);
}
static const struct file_operations lm75_proc_fops = {
.open = lm75_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif /*end LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0)*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
create_proc_read_entry(str, S_IFREG | S_IRUGO, NULL,
lm75_read_proc, (void *)dev_id);
#else
devp->procent = proc_create_data(str, S_IRUGO | S_IWUSR, NULL, \
&lm75_proc_fops, (void *)((uintptr_t)dev_id));
if (devp->procent == NULL) {
printk("proc_create failure: %s\n", str);
return -1;
}
#endif
再给一个别人的例子,作为参考:主要讲使用proc_create_data如何传递私有数据