zoukankan      html  css  js  c++  java
  • /proc/version 的生成过程

    /proc/version 的生成过程

    通常我们cat /proc/version时,会显示kernel相关的版本、编译等信息

    那么问题来了,这些信息是怎么生成的呢?

    /proc/version文件是在kernel fs/proc/version.c 中生成

    #include <linux/fs.h>                                               
    #include <linux/init.h>                                             
    #include <linux/kernel.h>                                           
    #include <linux/proc_fs.h>                                          
    #include <linux/seq_file.h>                                         
    #include <linux/utsname.h>                                          
                                                                        
    static int version_proc_show(struct seq_file *m, void *v)           
    {                                                                   
        seq_printf(m, linux_proc_banner,    //linux_proc_banner()在init/version.c中定义
            utsname()->sysname,          //utsname()在include/linux/utsname.h中定义
            utsname()->release,                                         
            utsname()->version);                                        
        return 0;                                                       
    }                                                                   
                                                                        
    static int version_proc_open(struct inode *inode, struct file *file)
    {                                                                   
        return single_open(file, version_proc_show, NULL);              
    }                                                                   
                                                                        
    static const struct file_operations version_proc_fops = {           
        .open       = version_proc_open,                                
        .read       = seq_read,                                         
        .llseek     = seq_lseek,                                        
        .release    = single_release,                                   
    };                                                                  
                                                                        
    static int __init proc_version_init(void)                           
    {                                                                   
        proc_create("version", 0, NULL, &version_proc_fops);            
        return 0;                                                       
    }                                                                   
    module_init(proc_version_init);                                     
    

    utsname()定义:

    //include/linux/utsname.h
    static inline struct new_utsname *utsname(void)
    {
        return &current->nsproxy->uts_ns->name;
    }
    
    //current 是一个宏,表示当前进程的指针
    //arch/arm/include/asm/current.h
    #ifndef _ASMARM_CURRENT_H
    #define _ASMARM_CURRENT_H
    
    #include <linux/thread_info.h>
    
    static inline struct task_struct *get_current(void) __attribute_const__;
    
    static inline struct task_struct *get_current(void)
    {
        return current_thread_info()->task;
    }
    
    #define current (get_current())
    
    #endif /* _ASMARM_CURRENT_H */
    
    //nsproxy, 是指kernel的namespace机制,关于机制,这里不展开。
    //nsproxy 的初始化的定义在./kernel/nsproxy.c文件中
    struct nsproxy init_nsproxy = {
        .count  = ATOMIC_INIT(1),
        .uts_ns = &init_uts_ns,
    #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
        .ipc_ns = &init_ipc_ns,
    #endif
        .mnt_ns = NULL,
        .pid_ns = &init_pid_ns,
    #ifdef CONFIG_NET
        .net_ns = &init_net,
    #endif
    };
    
    //该结构在task初始化的时候会被初始化,在include/linux/init_task.h文件中
    #define INIT_TASK(tsk)  
    ...
    .nsproxy    = &init_nsproxy,                
    ...
    
    //init_nsprosy定义在init/version.c中
    struct uts_namespace init_uts_ns = {
        .kref = {
            .refcount   = ATOMIC_INIT(2),
        },
        .name = {
            .sysname    = UTS_SYSNAME,
            .nodename   = UTS_NODENAME,
            .release    = UTS_RELEASE,
            .version    = UTS_VERSION,
            .machine    = UTS_MACHINE,
            .domainname = UTS_DOMAINNAME,
        },
        .user_ns = &init_user_ns,
    };
    EXPORT_SYMBOL_GPL(init_uts_ns);
    //到这里&current->nsproxy->uts_ns->name的路径就全部联系起来了。
    

    linux_proc_banner定义:

    #include <generated/compile.h>
    #include <linux/module.h>
    #include <linux/uts.h>
    #include <linux/utsname.h>
    #include <generated/utsrelease.h>
    #include <linux/version.h>
    
    #ifndef CONFIG_KALLSYMS
    #define version(a) Version_ ## a
    #define version_string(a) version(a)
    
    extern int version_string(LINUX_VERSION_CODE);
    int version_string(LINUX_VERSION_CODE);
    #endif
    
    struct uts_namespace init_uts_ns = {
        .kref = {
            .refcount   = ATOMIC_INIT(2),
        },
        .name = {
            .sysname    = UTS_SYSNAME,
            .nodename   = UTS_NODENAME,
            .release    = UTS_RELEASE,
            .version    = UTS_VERSION,
            .machine    = UTS_MACHINE,
            .domainname = UTS_DOMAINNAME,
        },
        .user_ns = &init_user_ns,
    };
    EXPORT_SYMBOL_GPL(init_uts_ns);
    
    /* FIXED STRINGS! Don't touch! */
    const char linux_banner[] =
        "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
        LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "
    ";
    
    const char linux_proc_banner[] =
        "%s version %s"
        " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
        " (" LINUX_COMPILER ") %s
    ";
    
    //那么,linux_proc_banner相当于
    //	"UTS_SYSNAME version UTS_RELEASE"
    //	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
    //	" (" LINUX_COMPILER ") UTS_VERSION
    ";
    
    /*
    * UTS_SYSNAME
    * UTS_NODENAME
    * UTS_RELEASE
    * UTS_VERSION
    * UTS_MACHINE
    * UTS_DOMAINNAME
    * LINUX_COMPILE_BY
    * LINUX_COMPILE_HOST
    * LINUX_COMPILER
    * 这些宏都是在编译kernel 是自动生成的。都放在include/generated/compile.h文件中
    */
    

    include/generated/compile.h

    #define UTS_MACHINE "arm"
    #define UTS_VERSION "#3 SMP PREEMPT Tue Jul 31 12:04:09 CST 2018"
    #define LINUX_COMPILE_BY "frank"
    #define LINUX_COMPILE_HOST "ubuntu"
    #define LINUX_COMPILER "gcc version 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 unknown) "
    

    那么问题又来了,compile.h是有谁生成的呢?

    在scripts/mkcompile_h脚本中。

  • 相关阅读:
    ubuntu 14.04 如何安装nvidia显卡驱动 [转载]
    torch Tensor学习:切片操作
    Graphviz(转载)
    torch 深度学习(5)
    torch 深度学习(4)
    torch 深度学习(3)
    torch 深度学习 (2)
    C# 初识Ref和Out
    Unity发送短信
    Unity 3D 动画帧事件
  • 原文地址:https://www.cnblogs.com/black-mamba/p/9396662.html
Copyright © 2011-2022 走看看