總結自linux下的seq_file.txt的document。虛擬檔案系統如procfs,debugfs等在建立虛擬檔案的時候,都要設計到虛擬檔案的操作。
使用虛擬檔案的時候比較挑戰的一點在於,當虛擬檔案相當大的時候,操作虛擬檔案需要一些技巧,在多次讀寫的時候要小心的操作檔案的position,當虛擬檔案的使用越來越廣泛的時候,這樣的操作**也越來越多,因此在2.6核心中加入了一組函式來方便實現虛擬檔案的操作,這就是seq_file。
seq_file宣告在
希望使用seq_file介面的模組都必須要要實現iterator物件來遍歷虛擬檔案的資料。
iterator介面包含4個函式需要實現用於遍歷:
struct seq_operations ;
1.1.1 start介面
start介面接受乙個pos作為起始位置,並且返回乙個iterator指標。對於乙個順序訪問的虛擬檔案來說,最簡單的start函式可能如下:
static void *ct_seq_start(struct seq_file *s, loff_t *pos)
對於順序訪問的檔案來說,只需要乙個loff_t來記錄虛擬檔案的當前訪問位置即可,這個loff_t就是iterator物件。
對於複雜的應用場景,seq_file中的private可以用來記錄資訊。
當start的pos為0的時候,start函式可以有乙個特殊的返回值seq_start_token,這個值從來讓show介面了解到當前正在起始位置從而輸出header資訊。
1.1.2 next介面
next介面用於將虛擬檔案位置移動pos個位置,引數v就是start介面中返回的iterator。
next介面會返回更新後的iterator,或者在沒有資料的時候返回null。
static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
1.1.3 stop介面
stop介面是做iterator物件的cleanup動作,主要就是釋放在start中申請的iterator物件。
static
void ct_seq_stop(struct seq_file *s, void *v)
1.1.4 show介面
show函式,將iterator指向的位置的物件進行格式化輸出。
static
int ct_seq_show(struct seq_file *s, void *v)
show函式正常都應該返回0,負數是表明發生了某些錯誤。
show函式可以返回seq_skip,表明當前的item會被skip,如果之前show已經產生過輸出,那麼這整個輸出都會被丟棄掉。
1.1.5 小結
seq_file在設計的時候,start()和stop()之間是不會sleep的,所以在start和stop之間持有乙個鎖是很合理的,除此之外,不會持有其他的鎖。
seq_file的主要功能就是管理虛擬檔案的位置,最終將輸出傳遞給使用者使用者。核心中提供了一組函式,用來幫助輸出內容。
int seq_printf(struct seq_file *m, const char *f, ...)
最常用的輸出函式是seq_printf,函式和printk類似,輸出內容儲存在seq_file的buffer中。
1.2.2 直接的字元輸出
int seq_putc(struct seq_file *m, char c);
int seq_puts(struct seq_file *m, const
char *s);
int seq_escape(struct seq_file *m, const
char *s, const
char *esc);
seq_putc和seq_puts很簡單,就是將乙個字元/字串輸入到seq_file中去。
seq_escape是在seq_puts的基礎上,將esc字串中所包含的字元都轉為用8進製的顯示。
在虛擬檔案中使用seq_file,需要實現一組file_operation,seq_file也提供給了一組可用的函式。
int seq_open(struct file *file, const
struct seq_operations *op);
seq_open中會使用seq_operations建立seq_file物件,並將其賦值給到file->private_data。seq_open常用來實現open操作,下面就是乙個最簡單的示例:
static
int ct_open(struct inode *inode, struct file *file)
對於read,lseek,release操作,seq_file中已經提供直接可用的函式:
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
loff_t seq_lseek(struct file *file, loff_t offset, int whence);
int seq_release(struct inode *inode, struct file *file);
簡單的例子如下:
static const struct file_operations ct_file_ops = ;
對於極端簡單的例子,可以使用乙個早期的介面single_open,
int single_open(struct file *file, int (*show)(struct seq_file *, void *),
void *data)
single_open完成的工作和seq_open類似,只是不需要編寫完整的seq_operation,只需要實現其中的show介面即可,其他介面會有預設的實現
和single_open配套的release函式是single_release
int single_release(struct inode *inode, struct file *file);
如果虛擬檔案被組織成list的形式,那麼下面的seq_list的函式會比較有用,方便實現對應的seq_operation操作。
struct list_head *seq_list_start(struct list_head *head,
loff_t pos);
struct list_head *seq_list_start_head(struct list_head *head,
loff_t pos);
struct list_head *seq_list_next(void *v, struct list_head *head,
loff_t *ppos);
補充閱讀程式 4
03.檔名稱 text.cpp 05.完成日期 2016年5月9日 06.版本號 vc 6.0 07.includeusing namespace std class a class b public a class b virtual public a class c public a class...
rt thread隨筆4補充 雙向鍊錶
typedef struct dnode dnode,doublelist 1 struct rt list node 2 6typedef struct rt list node rt list t rt list t 型別的節點裡面有兩個 rt list t 型別的節點指標 next 和 pre...
linux基礎學習 14 2 命令補充 4
1 userdel 刪除使用者 注釋引數 r 刪除使用者及使用者家目錄 2 groupadd 新增乙個使用者組 3 usermod 修改使用者資訊 u g g s m e c d l u l 小寫字母l 4 chage 專門修改使用者密碼資訊 引數 l 小寫字母l e m w m i 大寫字母i 5...