Я пытаюсь понять файлы последовательности в ядре Linux. ИМХО, они довольно непонятые звери, и с учетом этого я скомпилировал готовый модуль ядра из веб. Я воспроизвожу (измененный) код здесь для простоты доступа:
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
static int limit = 10; //default value, it can be changed here or
module_param(limit, int, S_IRUGO); //transfered as a module parameter
static int* even_ptr; //we will work with dynamic memory
/**
* start
*/
static void *ct_seq_start(struct seq_file *s, loff_t *pos) {
printk(KERN_INFO "Entering start(), pos = %Ld, seq-file pos = %lu.\n", *pos, s->count);
if ((*pos) >= limit) { // are we done?
printk(KERN_INFO "Apparently, we're done.\n");
return NULL;
}
//Allocate an integer to hold our increasing even value
even_ptr = kmalloc(sizeof(int), GFP_KERNEL);
if (!even_ptr) // fatal kernel allocation error
return NULL;
printk(KERN_INFO "In start(), even_ptr = 0x%pX.\n", even_ptr);
*even_ptr = (*pos)*2;
return even_ptr;
}
/**
* show
*/
static int ct_seq_show(struct seq_file *s, void *v) {
printk(KERN_INFO "In show(), even = %d.\n", *(int*)v);
seq_printf(s, "The current value of the even number is %d\n", *(int*)v);
// return (*(int *)v); // <-- Instead of a customary 'zero' I return the value of 'v' which is the actual even number that we are printing to the kernel log as well as the seq file
return 0;
}
/**
* next
*/
static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) {
printk(KERN_INFO "In next(), v = 0x%pX, *(int*)v=%d, pos=%Ld, seq-file pos=%lu.\n", v, *(int*)v, *pos, s->count);
(*pos)++; //increase my position counter
if (*pos >= limit) //are we done?
return NULL;
*(int*)v += 2; //to the next even value
return v;
}
/**
* stop
*/
static void ct_seq_stop(struct seq_file *s, void *v) {
printk(KERN_INFO "Entering stop().\n");
if (v)
printk(KERN_INFO "v is %pX.\n", v);
else
printk(KERN_INFO "v is null.\n");
printk(KERN_INFO "In stop(), even_ptr = %pX.\n", even_ptr);
if (even_ptr) {
printk(KERN_INFO "Freeing and clearing even_ptr.\n");
kfree(even_ptr);
even_ptr = NULL;
} else
printk(KERN_INFO "even_ptr is already null.\n");
}
/**
* This structure gathers functions which control the sequential reading
*/
static struct seq_operations ct_seq_ops = {
.start = ct_seq_start,
.next = ct_seq_next,
.stop = ct_seq_stop,
.show = ct_seq_show
};
/**
* This function is called when a file from /proc is opened
*/
static int ct_open(struct inode *inode, struct file *file) {
return seq_open(file, &ct_seq_ops);
};
/**
* This structure gathers functions for a /proc-file operations
*/
static struct file_operations ct_file_ops = {
.owner = THIS_MODULE,
.open = ct_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
/**
* This function is called when this module is loaded into the kernel
*/
static int __init ct_init(void) {
proc_create("evens", 0, NULL, &ct_file_ops);
return 0;
}
/**
* This function is called when this module is removed from the kernel
*/
static void __exit ct_exit(void) {
remove_proc_entry("evens", NULL);
}
module_init(ct_init);
module_exit(ct_exit);
MODULE_LICENSE("GPL");
Мой журнал ядра гласит:
Jun 30 19:10:22 mintab kernel: [ 8213.539959] Entering start(), pos = 0, seq-file pos = 0.
Jun 30 19:10:22 mintab kernel: [ 8213.539960] In start(), even_ptr = 0xffff9241772a8000.
Jun 30 19:10:22 mintab kernel: [ 8213.539960] In show(), even = 0.
Jun 30 19:10:22 mintab kernel: [ 8213.539962] In next(), v = 0xffff9241772a8000, *(int*)v=0, pos=0, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539962] In show(), even = 2.
Jun 30 19:10:22 mintab kernel: [ 8213.539963] In next(), v = 0xffff9241772a8000, *(int*)v=2, pos=1, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539963] In show(), even = 4.
Jun 30 19:10:22 mintab kernel: [ 8213.539964] In next(), v = 0xffff9241772a8000, *(int*)v=4, pos=2, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539964] In show(), even = 6.
Jun 30 19:10:22 mintab kernel: [ 8213.539965] In next(), v = 0xffff9241772a8000, *(int*)v=6, pos=3, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539965] In show(), even = 8.
Jun 30 19:10:22 mintab kernel: [ 8213.539966] In next(), v = 0xffff9241772a8000, *(int*)v=8, pos=4, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539966] In show(), even = 10.
Jun 30 19:10:22 mintab kernel: [ 8213.539967] In next(), v = 0xffff9241772a8000, *(int*)v=10, pos=5, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539967] In show(), even = 12.
Jun 30 19:10:22 mintab kernel: [ 8213.539968] In next(), v = 0xffff9241772a8000, *(int*)v=12, pos=6, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539969] In show(), even = 14.
Jun 30 19:10:22 mintab kernel: [ 8213.539969] In next(), v = 0xffff9241772a8000, *(int*)v=14, pos=7, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539970] In show(), even = 16.
Jun 30 19:10:22 mintab kernel: [ 8213.539970] In next(), v = 0xffff9241772a8000, *(int*)v=16, pos=8, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539971] In show(), even = 18.
Jun 30 19:10:22 mintab kernel: [ 8213.539971] In next(), v = 0xffff9241772a8000, *(int*)v=18, pos=9, seq-file pos=42.
Jun 30 19:10:22 mintab kernel: [ 8213.539972] Entering stop().
Jun 30 19:10:22 mintab kernel: [ 8213.539972] v is null.
Jun 30 19:10:22 mintab kernel: [ 8213.539972] In stop(), even_ptr = ffff9241772a8000.
Jun 30 19:10:22 mintab kernel: [ 8213.539973] Freeing and clearing even_ptr.
Jun 30 19:10:22 mintab kernel: [ 8213.539996] Entering start(), pos = 10, seq-file pos = 0.
Jun 30 19:10:22 mintab kernel: [ 8213.539996] Apparently, we're done.
Jun 30 19:10:22 mintab kernel: [ 8213.539997] Entering stop().
Jun 30 19:10:22 mintab kernel: [ 8213.539997] v is null.
Jun 30 19:10:22 mintab kernel: [ 8213.539997] In stop(), even_ptr = (null).
Jun 30 19:10:22 mintab kernel: [ 8213.539998] even_ptr is already null.
И файл proc выдает только следующий вывод, а затем останавливается: Текущее значение четного числа равно 0
Я исхожу из того, что подпрограмма «show» должна возвращать 0, чтобы считаться безошибочной для базовой файловой экосистемы seq. Однако разве маленькое положительное целое число не указывало бы на то же самое?? или они используются как-то по-другому??
UPDATE1: Как упоминалось в ответе нашего друга Цыварева, явно требуется вернуть 0 из подпрограммы show, как и все остальное считается неудачным, поэтому возвращается обратно соответственно. Сказав это, может ли кто-нибудь объяснить, почему мы снова вводим start после того, как исчерпали все числа, и v
, наконец, NULL
?? Мне особенно интересно знать, почему мы это делаем?
Jul 1 11:16:59 mintab kernel: [31765.915542] v is null.
Jul 1 11:16:59 mintab kernel: [31765.915542] In stop(), even_ptr = ffff9c7df619b340.
Jul 1 11:16:59 mintab kernel: [31765.915542] Freeing and clearing even_ptr.
Jul 1 11:16:59 mintab kernel: [31765.915551] Entering start(), pos = 200, seq-file pos = 0.
Jul 1 11:16:59 mintab kernel: [31765.915551] Apparently, we're done.
Jul 1 11:16:59 mintab kernel: [31765.915552] Entering stop().
Jul 1 11:16:59 mintab kernel: [31765.915552] v is null.
Jul 1 11:16:59 mintab kernel: [31765.915553] In stop(), even_ptr = (null).
Кроме того, приветствуются дополнительные ссылки на более подробное и (надеюсь) более простое объяснение механизма файла последовательности.