linux下可以通过 cat /proc/version 命令查看内核版本信息。

root@am57xx-evm:~# cat /proc/version
Linux version 4.14.79-gbde58ab01e (allen@david-virtual-machine) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #248 SMP PREEMPT Mon Dec 16 14:39:09 CST 2019

这个proc文件是在内核源码 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,
		utsname()->sysname,
		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;
}
fs_initcall(proc_version_init);

proc_create("version", 0, NULL, &version_proc_fops):
在proc目录下创建了version文件,打开这个文件时,会去调用其open方法,open里调用version_proc_show(),即执行下面这行代码:

seq_printf(m, linux_proc_banner,utsname()->sysname,utsname()->release,utsname()->version);

linux_proc_banner的定义在 init/version.c里:

const char linux_proc_banner[] =
	"%s version %s"
	" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
	" (" LINUX_COMPILER ") %s\n";

utsname()->sysname,->release,->version也在 init/version.c里初始化

struct uts_namespace init_uts_ns = {
	.kref = KREF_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,
	.ns.inum = PROC_UTS_INIT_INO,
#ifdef CONFIG_UTS_NS
	.ns.ops = &utsns_operations,
#endif
};

等价于:

seq_printf(m, "%s version %s (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") %s\n",UTS_SYSNAME,UTS_RELEASE,UTS_VERSION);

以我的环境为例:
UTS_SYSNAME:linux
UTS_RELEASE:4.14.79-gbde58ab01e ---根据MAkefile和内核配置生成
LINUX_COMPILE_BY:编译内核的用户
LINUX_COMPILE_HOST:编译内核的主机
LINUX_COMPILER:编译内核使用的编译器版本
UTS_VERSION:scripts/mkcompile_h里生成:

if [ -z "$KBUILD_BUILD_VERSION" ]; then
	if [ -r .version ]; then
		VERSION=`cat .version`
	else
		VERSION=0
		echo 0 > .version
	fi
else
	VERSION=$KBUILD_BUILD_VERSION
fi

if [ -z "$KBUILD_BUILD_TIMESTAMP" ]; then
	TIMESTAMP=`date`
else
	TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
fi
if test -z "$KBUILD_BUILD_USER"; then
	LINUX_COMPILE_BY=$(whoami | sed 's/\\/\\\\/')
else
	LINUX_COMPILE_BY=$KBUILD_BUILD_USER
fi
if test -z "$KBUILD_BUILD_HOST"; then
	LINUX_COMPILE_HOST=`hostname`
else
	LINUX_COMPILE_HOST=$KBUILD_BUILD_HOST
fi

UTS_VERSION="#$VERSION"
CONFIG_FLAGS=""
if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"

在这里UTS_VERSION="#$VERSION $CONFIG_FLAGS $TIMESTAMP",VERSION在KBUILD_BUILD_VERSION为空时,就是 .version文件的内容。.version里面记录的是内核编译次数,每编译一次这个文件中的值便会加1,删掉即可清零。

Logo

更多推荐