【发布时间】:2019-09-07 09:42:14
【问题描述】:
我编写了一个基本代码,它将使用 proc 文件中的 seq_file 打印进程名称。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/seq_file.h>
#include <linux/sched.h>
#include <linux/sched/task.h>
#include <linux/sched/signal.h>
MODULE_LICENSE("GPL");
static struct proc_dir_entry *dir_entry;
/**
* This function is called at the beginning of a sequence.
* ie, when:
* - the /proc file is read (first time)
* - after the function stop (end of sequence)
*
*/
static void *my_seq_start(struct seq_file *s, loff_t *pos)
{
loff_t index = *pos;
if (index == 0) {
seq_printf(s, "Current all the processes in system:\n"
"%-24s%-5s\n", "name", "pid");
return &init_task;
}
else {
return NULL;
}
}
/**
* This function is called after the beginning of a sequence.
* It's called untill the return is NULL (this ends the sequence).
*
*/
static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
struct task_struct *task = (struct task_struct *)v;
task = next_task(task);
if ((*pos != 0) && (task == &init_task)) {
return NULL;
}
++*pos;
return task;
}
/**
* This function is called at the end of a sequence
*
*/
static void my_seq_stop(struct seq_file *s, void *v)
{
}
/**
* This function is called for each "step" of a sequence
*
*/
static int my_seq_show(struct seq_file *s, void *v)
{
struct task_struct * task = (struct task_struct *)v;
seq_printf(s, "%-24s%-5d\n", task->comm, task->pid);
return 0;
}
static struct seq_operations my_seq_ops = {
.start = my_seq_start,
.next = my_seq_next,
.stop = my_seq_stop,
.show = my_seq_show
};
static int my_open(struct inode *inode, struct file *filp)
{
return seq_open(filp, &my_seq_ops);
}
static struct file_operations proc_ops =
{
.owner = THIS_MODULE,
.open = my_open, //user supplied
.read = seq_read, //interface supplied
.release = seq_release, //interface supplied
.llseek = seq_lseek //interface supplied
};
static int proc_init(void)
{
dir_entry = proc_mkdir("embedded", NULL);
proc_create("pid",0640,dir_entry,&proc_ops);
pr_info("ldd proc entry created\n");
return 0;
}
static void proc_cleanup(void)
{
remove_proc_entry("pid", dir_entry);
remove_proc_entry("embedded", NULL);
}
module_init(proc_init);
module_exit(proc_cleanup);
并非所有进程都被打印,它在打印 300 个进程后停止。我们可以使用procfs的seq api移动的迭代次数是否有任何限制。
我在上面的代码中有什么错误吗?我们可以用 seq api 只打印页面大小吗?
【问题讨论】:
-
30 * 300 = 9000 大于一页的大小。其他东西会阻止你看到所有这些。
-
所以,页面大小不是罪魁祸首。
-
"不是所有进程都打印出来,打印300个进程后就停止了。" - 你确定还有更多的流程吗?您是否尝试将一些
printk调用添加到my_seq_next函数中,例如进入返回 NULL 的分支? -
如果你 both
printk和seq_printk会打印相同数量的进程吗?请注意,使用next_task正确遍历任务意味着使用 RCU 读锁进行包装。否则可能会得到错误的任务列表(甚至导致一些错误)。 -
代码看起来不太安全。在您遍历列表时,可以创建或销毁进程。
标签: c linux linux-kernel linux-device-driver procfs