古早以前kernel對於proc資料的讀取都由read_proc這個callback函式處理,那它的prototype如下
- static int read_proc(char *page, char **start, off_t off, int count, int *eof,void *data)
kernel module傳給使用者的資料最終要印在page這個大小為4096bytes的空間裡,所以kernel moduel在處理使用者要讀取資料時要特別注意這個boundry,不過現在因為seq_file的出現,情勢會隨之改觀
seq_file比較特殊的是它提供一組讀取資料的callback API,分別為start,next,show,stop,而當使用者讀取資料時,它被呼叫的順序如下
start->show->next->show->next->show…>stop(沒資料了)
而在show這個印資料的function內,seq_file提供多組API給programmer使用
int seq_printf(struct seq_file *m, const char *f, ...):類似printf
int seq_puts(struct seq_file *m, const char *s):印字串
int seq_putc(struct seq_file *m, char c):印字元
從上面幾個函式可以看到,seq_file的讀取完全沒有4k boundry的限制,而且依照它這樣的讀取資料流程,可以發現,seq_file很適合處理list型態的資料,我下面有個很簡單的範例,重點就在我剛剛提到的start,next,show,stop,因為我的string array size只有3個,所以在seq_start會對目前的offset判斷有沒有超過array size
- #include <linux/kernel.h> /* We're doing kernel work */
- #include <linux/module.h> /* Specifically, a module */
- #include <linux/proc_fs.h> /* Necessary because we use proc fs */
- #include <linux/seq_file.h> /* for seq_file */
-
- #define PROC_NAME "iter"
- #define dbg(fmt,args...) printk("[%s]:%d => "fmt,__FUNCTION__,__LINE__,##args)
- #define DBG() printk("[%s]:%d => \n",__FUNCTION__,__LINE__)
-
- static char *sampleArray[3]={"string1","string2","string3"};
-
-
- static void *my_seq_start(struct seq_file *s, loff_t *pos)
- {
- //DBG();
- if (*pos>=3) return NULL;
- return (void *)((unsigned long) *pos+1);
- }
-
- static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos)
- {
- ++*pos;
- return my_seq_start(s, pos);
- }
-
- static void my_seq_stop(struct seq_file *s, void *v)
- {
- //DBG();
-
- }
-
- static int my_seq_show(struct seq_file *s, void *v)
- {
-
- //unsigned long n;
- int n;
-
- //DBG();
- n = (int)v-1;
- seq_printf(s,"sampleArray[%d]:%s\n",n,sampleArray[n]);
- 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 *file)
- {
- //DBG();
- return seq_open(file, &my_seq_ops);
- };
-
- static struct file_operations my_file_ops = {
- .owner = THIS_MODULE,
- .open = my_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release
- };
-
- int init_module(void)
- {
- struct proc_dir_entry *entry;
- entry = create_proc_entry(PROC_NAME, 0, NULL);
- if (entry) {
- entry->proc_fops = &my_file_ops;
- }
- return 0;
- }
-
- void cleanup_module(void)
- {
- remove_proc_entry(PROC_NAME, NULL);
- }
-
- MODULE_DESCRIPTION("seq module");
- MODULE_AUTHOR("Joey Cheng<jemicheng@gmail.com>");
- MODULE_LICENSE("GPL");
- MODULE_ALIAS("QT2410:seq module");
此範例執行時會把string array內的資料讀取出來,如下圖

範例程式碼在此下載
Regular expression-跟brainfuck差不多的東西 (2009-11-13 15:37)
Reading file in kernel-簡單但實用 (2009-10-13 15:18)
Linux file system for dummies-只花你45分鐘 (2009-08-19 15:40)
OPENSSL-TCP SSL初心者之路 (2009-07-16 15:16)
NAPI與pure interrupt driver的效能比較 (2009-04-29 19:06)
usermode helper-來自kernel的呼喚 (2009-04-21 16:19)
kernel module memory detector-抓出有害的kernel module (2009-03-31 13:50)
kernel space coding-如履薄冰 (2009-03-26 09:52)
readahead與posix_advise-預讀取是萬能靈丹? (2009-03-06 15:54)