(just FYI, i used to think i knew all about seq_files. but there's nothing like trying to write about something to make you realize there's lots you *don't* know.) ok, i have two more questions/observations about seq_files, then i think i'll be sick of them. consider a sample loadable module stolen from the samples for LDD3. the parts i added i've commented with "//rday". and i've snipped out some parts that aren't relevant. ===== #include <linux/init.h> #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/fs.h> #include <linux/seq_file.h> #include <linux/slab.h> MODULE_LICENSE("Dual BSD/GPL"); static void *ct_seq_start(struct seq_file *s, loff_t *pos) { seq_printf(s, "Entering start, pos = %Ld.\n", *pos); // rday loff_t *spos = kmalloc(sizeof(loff_t), GFP_KERNEL); if (!spos) return NULL; *spos = *pos; return spos; } static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) { seq_printf(s, "Entering next.\n"); loff_t *spos = (loff_t *) v; *pos = ++(*spos); return spos; } static void ct_seq_stop(struct seq_file *s, void *v) { seq_printf(s, "Entering stop."); // rday kfree (v); } static int ct_seq_show(struct seq_file *s, void *v) { seq_printf(s, "Entering show.\n"); loff_t *spos = (loff_t *) v; seq_printf(s, "%Ld\n", *spos); return 0; } static struct seq_operations ct_seq_ops = { .start = ct_seq_start, .next = ct_seq_next, .stop = ct_seq_stop, .show = ct_seq_show }; static int ct_open(struct inode *inode, struct file *file) { return seq_open(file, &ct_seq_ops); }; static struct file_operations ct_file_ops = { .owner = THIS_MODULE, .open = ct_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release }; static int ct_init(void) { struct proc_dir_entry *entry; entry = create_proc_entry("sequence", 0, NULL); if (entry) entry->proc_fops = &ct_file_ops; return 0; } static void ct_exit(void) { remove_proc_entry("sequence", NULL); } module_init(ct_init); module_exit(ct_exit); ===== i've tested the above and it seems to work just fine -- prints infinitely until you tell it to stop. so here's what i discovered. first, consider the "start" routine: ===== static void *ct_seq_start(struct seq_file *s, loff_t *pos) { seq_printf(s, "Entering start, pos = %Ld.\n", *pos); // rday loff_t *spos = kmalloc(sizeof(loff_t), GFP_KERNEL); if (!spos) return NULL; *spos = *pos; return spos; } ===== i noticed that, on each call to this routine, a new pointer to the "offset" is dynamically allocated, and a *copy* is made there. and during each call to the stop routine, that value is freed. yes, that works. but other examples of seq files i've seen simply use the value pointed at directly by "pos". is there some advantage to making your own copy of that? other than leaving the original value untouched, does that make the seq file re-entrant, or something? is there an actual benefit to doing it as above? secondly, i finally noticed how the start routine is called multiple times. i loaded the module, then listed the contents of the corresponding /proc/sequence file, and saw: Entering start, pos = 0. Entering show. 0 Entering next. Entering show. 1 Entering next. Entering show. 2 ... 121 Entering next. Entering show. 122 Entering stop^@Entering start, pos = 123. Entering show. 123 ... 241 Entering next. Entering show. 242 Ent^@Entering start, pos = 243. Entering show. 243 ... ok, *now* i get it. the seq file implementation itself keeps "printing" until, what, it has close to a page of output, then "stops", then restarts at the next value and so on? that makes sense, i just didn't immediately see why the start routine would be called multiple times. so does that occasional stop/start combination represent a "page" of output from the file? thanks. rday -- ======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA Linux Consulting, Training and Annoying Kernel Pedantry. Web page: http://crashcourse.ca Twitter: http://twitter.com/rpjday "Kernel Newbie Corner" column @ linux.com: http://cli.gs/WG6WYX ======================================================================== -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ