proc接口变化

    ldd3中提到使用read_proc接口调试驱动,再通过create_proc_read_entry与/proc入口项连接,我在4.13.0的内核中调试,发现这两个接口都消失了。

    /proc/modules记录了内核加载的驱动列表,那么这个一定是使用了proc文件系统,在内核中查找"modules",发现了kernel/modules.c,肯定是这个文件创建了/proc/modules,打开后看到

static const struct file_operations proc_modules_operations = {     
    .open       = modules_open,
    .read       = seq_read,
    .llseek     = seq_lseek,
    .release    = seq_release,
};

static int __init proc_modules_init(void)
{
    proc_create("modules", 0, NULL, &proc_modules_operations);
    return 0;
}                                                                   
module_init(proc_modules_init);                                                  

    发现使用了proc_create接口,与一个file_operations结构关联,其中seq_read, seq_lseek, seq_release都是内核中的函数,只实现了modules_open

static const struct seq_operations modules_op = {                  
    .start  = m_start,                                             
    .next   = m_next,                                              
    .stop   = m_stop,                                              
    .show   = m_show                                               
};                                                                 
                                                                   
static int modules_open(struct inode *inode, struct file *file)    
{                                                                  
    return seq_open(file, &modules_op);                            
}                                                                  
    open中只调用了seq_open,看到一个新的结构seq_operations,结构中的四个成员应该就是在读取/proc下的文件时内核会去调用的接口
/* Called by the /proc file system to return a list of modules. */       
static void *m_start(struct seq_file *m, loff_t *pos)                    
{                                                                        
    mutex_lock(&module_mutex);                                           
    return seq_list_start(&modules, *pos);                               
}                                                                        
                                                                         
static void *m_next(struct seq_file *m, void *p, loff_t *pos)            
{                                                                        
    return seq_list_next(p, &modules, pos);                              
}                                                                        
                                                                         
static void m_stop(struct seq_file *m, void *p)                          
{                                                                        
    mutex_unlock(&module_mutex);                                         
}                                                                        
                                                                         
static int m_show(struct seq_file *m, void *p)                           
{                                                                        
    struct module *mod = list_entry(p, struct module, list);             
    char buf[MODULE_FLAGS_BUF_SIZE];                                     
                                                                         
    /* We always ignore unformed modules. */                             
    if (mod->state == MODULE_STATE_UNFORMED)                             
        return 0;                                                        
                                                                         
    seq_printf(m, "%s %u",                                               
           mod->name, mod->init_layout.size + mod->core_layout.size);    
    print_unload_info(m, mod);                                           
                                                                         
    /* Informative for users. */                                         
    seq_printf(m, " %s",                                                 
           mod->state == MODULE_STATE_GOING ? "Unloading" :              
           mod->state == MODULE_STATE_COMING ? "Loading" :               
           "Live");                                                      
    /* Used by oprofile and other similar tools. */                      
    seq_printf(m, " 0x%pK", mod->core_layout.base);        
                                                           
    /* Taints info */                                      
    if (mod->taints)                                       
        seq_printf(m, " %s", module_flags(mod, buf));      
                                                           
    seq_puts(m, "\n");                                     
    return 0;                                              
}                                                          
    往后看书发现也说到了这种方法,并且提到是对/proc代码的整理而增加的seq_file接口,与老的方法比较在输出大量数据时可以不用担心缓冲区大小问题。验证后发现其调用顺序为start->show->next->show->next->show.......->next->stop->start->stop,需要注意的是在show方法中如果没有返回值,内核并不会报错,但是流程上最后的start->stop会没有,并且终端不会有任何输出。书上所使用的连接seq_file和/proc的create_proc_entry接口也没有了,可以使用新的proc_create,但是注意在卸载模块时需要删除/proc入口项,否则在下次安装驱动时注册了同一入口将导致proc文件系统出现问题,此时如果再使用/proc目录将导致系统崩溃。kernel/module.c里似乎没有移除入口项,可能是这个模块在内核启动时调用,之后并不会卸载,看书上移除是使用remove_proc_entry接口,查看include/linux/proc_fs.h发现还有
extern void remove_proc_entry(const char *, struct proc_dir_entry *);  

    正常调用就可以了。

可以参考的文件:

include/linux/proc_fs.h

include/linux/seq_file.h

kernel/module.c

Documentation/filesystems/seq_file.txt



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值