"Kernel version" 中编译时间的前世今生
来源:互联网 发布:debian和ubuntu哪个好 编辑:程序博客网 时间:2024/05/17 02:26
"Kernel version" 中编译时间的前世今生
我们经常为固定编译时间,这个时间一般是指 Settings -> About phone -> Kernel version 中的时间,那么,这个时间到底怎么来的呢?
Settings中用于显示Kernel version的关键代码如下:[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
// packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java
public
void
onCreate(Bundle icicle) {
...
// 设置版本号
findPreference(KEY_KERNEL_VERSION).setSummary(getFormattedKernelVersion());
...
}
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
// packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java
public
static
String getFormattedKernelVersion() {
...
// 从"/proc/version"文件中读取编译信息,通过解析,组合出想要显示的版本号
return
formatKernelVersion(readLine(FILENAME_PROC_VERSION));
...
}
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java
public
static
String formatKernelVersion(String rawKernelVersion) {
// Example (see tests for more):
// Linux version 3.0.31-g6fb96c9 ([url=mailto:android-build@xxx.xxx.xxx.xxx.com]android-build@xxx.xxx.xxx.xxx.com[/url]) \
// (gcc version 4.6.x-xxx 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT \
// Thu Jun 28 11:02:39 PDT 2012
final
String PROC_VERSION_REGEX =
"Linux version (\\S+) "
+
/* group 1: "3.0.31-g6fb96c9" */
"\\((\\S+?)\\) " + /* group 2: "x@y.com" (kernel builder) */
"(?:\\(gcc.+? \\)) " + /* ignore: GCC version information */
"(#\\d+) " + /* group 3: "#1" */
"(?:.*?)?" + /* ignore: optional SMP, PREEMPT, and any CONFIG_FLAGS */
"((Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */
// 解析版本信息
Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion);
...
// 组合出想要的版本号
return
m.group(
1
) +
"\n"
+
// 3.0.31-g6fb96c9
m.group(
2
) +
" "
+ m.group(
3
) +
"\n"
+
// [url=mailto:x@y.com]x@y.com[/url] #1
m.group(
4
);
// Thu Jun 28 11:02:39 PDT 2012
}
我们可以看到,Kernel version是通过解析"/proc/version"文件得到的,而"/proc/version" 则是被"kernel-3.10/fs/proc/version.c"生成的:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
//kernel-3.10/fs/proc/version.c
// 创建 "/proc/version" 文件后用到的回调函数
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/version" 文件, 并注册回调函数
proc_create(
"version"
, 0, NULL, &version_proc_fops);
return
0;
}
[C] 纯文本查看 复制代码
1
2
3
4
5
6
7
// kernel-3.10/fs/proc/version.c
// 创建完成后通过回调函数调用
static
int
version_proc_open(
struct
inode *inode,
struct
file *file)
{
// 打开"/proc/version" 文件, 并注册回调函数"version_proc_show()"
return
single_open(file, version_proc_show, NULL);
}
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
//kernel-3.10/fs/proc/version.c
// 打开文件完成后通过回调函数调用
static
int
version_proc_show(
struct
seq_file *m,
void
*v)
{
// 输出编译信息到"/proc/version" 文件
// "linux_proc_banner"为format string,定义 kernel-3.10/init/version.c 中
// utsname(),内联函数,定义在 kernel-3.10/include/linux/utsname.h 中
seq_printf(m, linux_proc_banner,
utsname()->sysname,
utsname()->release,
utsname()->version);
// version 包括了编译时间
return
0;
}
[C] 纯文本查看 复制代码
1
2
3
4
// kernel-3.10/include/linux/utsname.hstatic inline struct new_utsname *utsname(void)
{
return
¤t->nsproxy->uts_ns->name;
}
[C] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
// kernel-3.10/include/linux/nsproxy.h
struct
nsproxy { atomic_t count;
struct
uts_namespace *uts_ns;
struct
ipc_namespace *ipc_ns;
struct
mnt_namespace *mnt_ns;
struct
pid_namespace *pid_ns;
struct
net *net_ns;
};
uts_ns的初始化在kernel-3.10/kernel/nsproxy.c中:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
// kernel-3.10/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
};
可以看到uts_ns = &init_uts_ns, init_uts_ns的定义在kernel-3.10/init/version.c 中:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
// kernel-3.10/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,
.proc_inum = PROC_UTS_INIT_INO,
};
我们可以看到version = UTS_VERSION,UTS_VERSION这个宏定义在compile.h中,这是一个生成文件,是被 kernel-3.10/scripts/mkcompile_h 这个脚本生成的,生成路径为(g3557为当前所编译的项目名):
./out/target/product/g3557/obj/KERNEL_OBJ/include/generated/compile.h
[Shell] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# kernel-3.10/scripts/mkcompile_h
# 通过抓Log,$KBUILD_BUILD_TIMESTAMP 为空
if
[ -z
"$KBUILD_BUILD_TIMESTAMP"
];
then
# 获取系统当前的日期和时间
TIMESTAMP=`
date
`
else
TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
fi
# 组合出UTS_VERSION
UTS_VERSION=
"$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
# Generate a temporary compile.h
(
echo
/\* This
file
is auto generated, version $VERSION \*/
if
[ -n
"$CONFIG_FLAGS"
] ;
then
echo
"/* $CONFIG_FLAGS */"
;
fi
echo
\
#define UTS_MACHINE \"$ARCH\"
# 输出UTS_VERSION 到compile.h
echo
\
#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
echo
\
#define LINUX_COMPILE_BY \"`echo $LINUX_COMPILE_BY | $UTS_TRUNCATE`\"
echo
\
#define LINUX_COMPILE_HOST \"`echo $LINUX_COMPILE_HOST | $UTS_TRUNCATE`\"
echo
\
#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
) > .tmpcompile
0 0
- "Kernel version" 中编译时间的前世今生
- linux kernel 时钟系统的前世今生
- android 中 setContentView() 的前世今生
- 前世今生的缘
- 互联网的前世今生
- 救世主的前世今生
- 3G的前世今生
- Gentoo的前世今生
- Mozilla的前世今生
- Java的“前世今生”
- unix的前世今生
- 浏览器的前世今生
- JAVA的前世今生
- bug的前世今生
- CKO的前世今生
- BIM的前世今生
- XVID的前世今生
- ActionScript的前世今生
- C++作业3-类和对象2
- 通过按钮跳过SplashActivity(启动画面),延时自动跳过SplashActivity进入MainActivity
- 鸟哥linux 学习笔记 第六章
- POJ 1236 —— Network of Schools
- NYOJ 1129 Salvation(技巧型深搜)
- "Kernel version" 中编译时间的前世今生
- 内存管理:栈区,堆区,全局区,文字常量区,程序代码区
- Hibernate学习总结:OneToOne单向外键关联
- Fatal error: Call to a member function fetch_array() on a non-object in E:\wamp\www\shop\index.php
- 几种常见的存储方式
- poj1170(状态压缩dp)
- 电量统计之一:PowerProfile.java与power_profile.xml
- 结构体日期计算
- POJ 1251.Jungle Roads【最小生成树】【4月15】