?????
????procfs???????????е???????????????????????????????: ??????????洢?豸?е???????????????????С?procfs?е???????????????????????????????е??Щ????????????????? /proc/[0-9]+/ ?У?????????????????????? /proc/ksyms ?????????г???????????????????Щ??????????????????????????и???????????????????????????????????????顣????ksyms??insmod??kmod????????????????г??????????е????????????????????????PID????
?????????????????????procfs?????????á???????????к?????????????????????????????????????????????????????????ЩС???ɡ???????????????????????????????
??????? /proc/sys ?е????????sysctl??????????????procfs????????????????????????api?????
????seq_file
????procfs???????????е???????????procfs????????????????Щ???????? seq_file ????? seq_file ??????????????????????????????????
????seq_file ???????????????y?????????????????????????????????????? seq_file ???????????????”iterator”????????????????????У?????????????????????е??????????????????????е??????????????????????????????????????????????????????????????????????????
????????????????????? <Linux/seq_file.h> ?????????????????????????????start?? next?? stop?? and show??
????start ???????????????á??????????????????:
????void *start(struct seq_file *sfile?? loff_t *pos);
????sfile??????????????????pos??????????????????????λ????????????λ?????????????????????????????????????е???????λ?á? ???? seq_file ???????????????????????????????????λ????????????????????????????????????wing?????У??????豸????????е????????????????pos????g_pstWingDevices?????????????????wing??????start????????????
????static void *wing_seq_start(struct seq_file *s?? loff_t *pos)
????{
????if (*pos >= g_iWingDevicesNum)
????return NULL; /* No more to read */
????return g_pstWingDevices + *pos;
????}
???????????????NULL????????????????????????????????
????next ???????????????????????λ????????????????????????NULL????????????????????
????void *next(struct seq_file *sfile?? void *v?? loff_t *pos);
????????????v????????????????????????start????????????next???????????????????? ????pos??????е???λ?á?next?????????pos???????????????仹????????????????????????????next??????wing?????е???????
????static void* wing_seq_next(struct seq_file *s?? void *v?? loff_t *pos)
????{
????(*pos)++;
????if (*pos >= g_iWingDevicesNum)
????return NULL;
????return g_pstWingDevices + *pos;
????}
???????????????????????????????stop?????????????
????void stop(struct seq_file *sfile?? void *v);
????wing???????????????????????stop????????
????void wing_seq_stop(struct seq_file *sfile?? void *v)
????{
????}
??????? seq_file ?????????start??stop????????????????????????????????????????塣????????start?????????stop?????????????????????????????л?????????????????????????????????????seq_file????????????????????????????????????
????????Щ?????????У???????call??????????????????????????????????????????
????· int show(struct seq_file *sfile?? void *v);
?????????????????????????????v??????????????????printk???????????????Щ?????????
????· int seq_printf(struct seq_file *sfile?? const char *fmt?? ...)
????????????? seq_file ????????????printf???????????????????????????????????????????????show?????е? seq_file ???崫??????????????????????????????????buffer???????????????????????????????У???????????????
????· int seq_putc(struct seq_file *sfile?? char c);
????· int seq_puts(struct seq_file *sfile?? const char *s);
????????????????????????putc??puts??
????· int seq_escape(struct seq_file *m?? const char *s?? const char *esc);
????????????? seq_puts ?????壬 ???? s ?е??κ???? esc ?г??????????????????. esc ???????????” ”?? ?????????????????????????? shell ???.
????· int seq_path(struct seq_file *sfile?? struct vfsmount *m?? struct dentry *dentry?? char *esc);
????????????????????????????????????????????. ?????豸?????в?????????;?????????????????????.
????wing?豸?е?show????????:
????static int wing_seq_show(struct seq_file *s?? void *v)
????{
????ST_Wing_Dev_Type* pDev = (ST_Wing_Dev_Type* ) v;
????seq_printf(s?? " This Device is %i "?? pDev->iData);
????return 0;
????}
??????????????У??????? ST_Wing_Dev_Type ???????????????
???????????????????????????wing?????????????????????????procfs???????????????????????????????? seq_operations ???壺
????static struct seq_operations s_stWingSeqOps = {
????.start = wing_seq_start??
????.next = wing_seq_next??
????.stop = wing_seq_stop??
????.show = wing_seq_show
????};
??????????????????????????????????????????????????????????? read_proc ??????????? seq_file ??? ?????????????????????procfs??????ζ???????? file_operations (??????豸??????)?????????????????????reads??seeks??????????????????????????????????????????? seq_file ??????????????open??????
????static int wing_proc_open(struct inode *inode?? struct file *file)
????{
????return seq_open(file?? &s_stWingSeqOps);
????}
???????? seq_open ?????????????????漲??????в????????????open??????????????????????????? file_operations ???????
????static struct file_operations s_stWingProcFops = {
????.owner = THIS_MODULE??
????.open = wing_proc_open??
????.read = seq_read??
????.llseek = seq_lseek??
????.release = seq_release
????};
?????????????procfs??????д????????
????proc_create("wingdevices"?? 0644?? NULL?? &s_stWingProcFops);
???????????
????struct proc_dir_entry ???????/proc???μ???????????????????procfs?????????????壬????????? /fs/internal.h ?У?
/*
* This is not completely implemented yet. The idea is to
* create an in-memory tree (like the actual /proc filesystem
* tree) of these proc_dir_entries?? so that we can dynamically
* add new files to /proc.
*
* The "next" pointer creates a linked list of one /proc directory??
* while parent/subdir create the directory structure (every
* /proc file has a parent?? but "subdir" is NULL for all
* non-directory entries).
*/
struct proc_dir_entry {
unsigned int low_ino;
umode_t mode;
nlink_t nlink;
kuid_t uid;
kgid_t gid;
loff_t size;
const struct inode_operations *proc_iops;
const struct file_operations *proc_fops;
struct proc_dir_entry *next?? *parent?? *subdir;
void *data;
atomic_t count;     /* use count */
atomic_t in_use;    /* number of callers into module in progress; */
/* negative -> it's going away RSN */
struct completion *pde_unload_completion;
struct list_head pde_openers;   /* who did ->open?? but not ->release */
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
u8 namelen;
char name[];
};
??????????
????procfs??e????????? <linux/proc_fs.h> ??
??????3.x?????procfs???????У?
proc_symlink
proc_mkdir
proc_mkdir_data
proc_mkdir_mode
proc_create_data
proc_create
proc_set_size
proc_set_user
PDE_DATA
proc_get_parent_data
proc_remove
remove_proc_entry
remove_proc_subtree
proc_mkdir
???????????/proc?′?????
????????????
????struct proc_dir_entry *proc_mkdir(const char *name?? struct proc_dir_entry *parent)
??????????
????· name
?????????????????
????· parent
??????????????NULL??????????/proc???洴??????
????proc_mkdir_data
???????????/proc?′?????
????????????
????struct proc_dir_entry *proc_mkdir_data(const char *name?? umode_t mode?? struct proc_dir_entry *parent?? void *data)
??????????
????· name
?????????????????
????· mode
???????????????????
????parent
??????????????NULL??????????/proc???洴??????
????· data
????proc_create_data
?????????????proc????????????
????????????
????struct proc_dir_entry *proc_create_data(const char *name?? umode_t mode??
????struct proc_dir_entry *parent??
????const struct file_operations *proc_fops??
????void *data)
??????????
????· name
????????????????????
????· mode
????????????????????
????· parent
????????????????????????????name????????磺init_net.proc_net?????/proc/net/??????????
????· proc_fops
?????struct file_operations
????· data
????????????????????粻??NULL??
?????????
////////////////////////test.c////////////////////////////////////////
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/net_namespace.h>
#include <linux/mm.h>
MODULE_LICENSE("GPL");
typedef struct {
int data1;
int data2;
}ST_Data_Info_Type;
static ST_Data_Info_Type g_astDataInfo[2];
static int test_proc_show(struct seq_file *m?? void *v)
{
ST_Data_Info_Type* pInfo = (ST_Data_Info_Type*)m->private;
if(pInfo != NULL)
{
seq_printf(m?? "%d----%d "?? pInfo->data1?? pInfo->data2);
}
return 0;
}
static int test_proc_open(struct inode *inode?? struct file *file)
{
return single_open(file?? test_proc_show?? PDE_DATA(inode));
}
static const struct file_operations dl_file_ops = {
.owner = THIS_MODULE??
.open    = test_proc_open??
.read    = seq_read??
.llseek  = seq_lseek??
.release = single_release??
};
static struct proc_dir_entry *s_pstRootTestDir;
void init_mem(void)
{
/* create /proc/test */
s_pstRootTestDir = proc_mkdir("test"?? NULL);
if (!s_pstRootTestDir)
return;
g_astDataInfo[0].data1=1;
g_astDataInfo[0].data2=2;
proc_create_data("proc_test1"?? 0644?? s_pstRootTestDir?? &dl_file_ops?? &g_astDataInfo[0]);
g_astDataInfo[1].data1=3;
g_astDataInfo[1].data2=4;
proc_create_data("proc_test2"?? 0644?? s_pstRootTestDir?? &dl_file_ops?? &g_astDataInfo[1]);
}
static int __init test_module_init(void)
{
printk("[test]: module init ");
init_mem();
return 0;
}
static void __exit test_module_exit(void)
{
printk("[test]: module exit ");
remove_proc_entry("proc_test1"?? s_pstRootTestDir);
remove_proc_entry("proc_test2"?? s_pstRootTestDir);
remove_proc_entry("test"?? NULL);
}
module_init(test_module_init);
module_exit(test_module_exit);
proc_create
?????????????proc????????????
????????????
????struct proc_dir_entry *proc_create(const char *name?? umode_t mode?? struct proc_dir_entry *parent?? const struct file_operations *proc_fops)
??????????
????· name
????????????????????
????· mode
????????????????????
????· parent
????????????????????????????name????????磺init_net.proc_net?????/proc/net/??????????
????· proc_fops
?????struct file_operations
?????????????? proc_create_data ?????????????????????????????
????PDE_DATA
??????? proc_create_data ?????????????
????proc_symlink
??????????????????procfs???′????????name???dest?????????. ???????????Ч? ln -s dest name ??
????????????
????struct proc_dir_entry *proc_symlink(const char *name?? struct proc_dir_entry *parent?? const char *dest)
??????????
????· name
???????????
????· parent
?????????????????
????· dest
?????????????????????????
????remove_proc_entry
????????????procfs??????е????????????
????????????
????void remove_proc_entry(const char *name?? struct proc_dir_entry *parent)
??????????
????· name
???????????????????????
????· parent
?????????????????????NULL???????/proc?????