02
03

seq_file-讀取proc資料的新選擇

古早以前kernel對於proc資料的讀取都由read_proc這個callback函式處理,那它的prototype如下

  1. 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

  1. #include <linux/kernel.h> /* We're doing kernel work */
  2. #include <linux/module.h> /* Specifically, a module */
  3. #include <linux/proc_fs.h> /* Necessary because we use proc fs */
  4. #include <linux/seq_file.h> /* for seq_file */
  5.  
  6. #define PROC_NAME "iter"
  7. #define dbg(fmt,args...) printk("[%s]:%d => "fmt,__FUNCTION__,__LINE__,##args)
  8. #define DBG() printk("[%s]:%d => \n",__FUNCTION__,__LINE__)
  9.  
  10. static char *sampleArray[3]={"string1","string2","string3"};
  11.  
  12. /**
  13. * This function is called at the beginning of a sequence.
  14. * ie, when:
  15. * 1.the /proc file is read (first time)
  16. * 2.after the function stop (end of sequence)
  17. *
  18. */ 
  19. static void *my_seq_start(struct seq_file *s, loff_t *pos) 
  20. { 
  21. //DBG();
  22. if (*pos>=3) return NULL;
  23. return (void *)((unsigned long) *pos+1);
  24. } 
  25. /**
  26. * This function is called after the beginning of a sequence.
  27. * It's called untill the return is NULL (this ends the sequence).
  28. *
  29. */ 
  30. static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos) 
  31. { 
  32. ++*pos;
  33. return my_seq_start(s, pos);
  34. } 
  35. /**
  36. * This function is called at the end of a sequence
  37. *
  38. */ 
  39. static void my_seq_stop(struct seq_file *s, void *v) 
  40. { 
  41. //DBG();
  42. /* nothing to do, we use a static value in start() */ 
  43. } 
  44. /**
  45. * This function is called for each "step" of a sequence
  46. *
  47. */ 
  48. static int my_seq_show(struct seq_file *s, void *v) 
  49. { 
  50.  
  51. //unsigned long n;
  52. int n;
  53.  
  54. //DBG();
  55. n = (int)v-1;
  56. seq_printf(s,"sampleArray[%d]:%s\n",n,sampleArray[n]);
  57. return 0;
  58. } 
  59. /**
  60. * This structure gather "function" to manage the sequence
  61. *
  62. */ 
  63. static struct seq_operations my_seq_ops = { 
  64. .start = my_seq_start,
  65. .next = my_seq_next,
  66. .stop = my_seq_stop,
  67. .show = my_seq_show 
  68. };
  69. /**
  70. * This function is called when the /proc file is open.
  71. *
  72. */ 
  73. static int my_open(struct inode *inode, struct file *file) 
  74. { 
  75. //DBG();
  76. return seq_open(file, &my_seq_ops);
  77. };
  78. /**
  79. * This structure gather "function" that manage the /proc file
  80. *
  81. */ 
  82. static struct file_operations my_file_ops = { 
  83. .owner = THIS_MODULE,
  84. .open = my_open,
  85. .read = seq_read,
  86. .llseek = seq_lseek,
  87. .release = seq_release 
  88. };
  89. /**
  90. * This function is called when the module is loaded
  91. *
  92. */ 
  93. int init_module(void) 
  94. { 
  95. struct proc_dir_entry *entry;
  96. entry = create_proc_entry(PROC_NAME, 0, NULL);
  97. if (entry) { 
  98. entry->proc_fops = &my_file_ops;
  99. } 
  100. return 0;
  101. } 
  102. /**
  103. * This function is called when the module is unloaded.
  104. *
  105. */ 
  106. void cleanup_module(void) 
  107. { 
  108. remove_proc_entry(PROC_NAME, NULL);
  109. } 
  110.  
  111. MODULE_DESCRIPTION("seq module");
  112. MODULE_AUTHOR("Joey Cheng<jemicheng@gmail.com>");
  113. MODULE_LICENSE("GPL");
  114. MODULE_ALIAS("QT2410:seq module");

此範例執行時會把string array內的資料讀取出來,如下圖

範例程式碼在此下載

標籤: linux
評論: 1 | 引用: 0 | 閱讀: 10154
  • 1 
愛你 [ 2010-07-20 10:56 | 回覆 | 編輯 刪除 ]
感謝大大分享 有下有推
  • 1 
發表評論
暱 稱: 密 碼:
網 址: E - mail:
驗證碼: 驗證碼圖片 選 項:
頭 像:
內 容: