How to change Kernel Version String
14 Feb 2015OS: Android 4.4 Kernel: 3.10.28
这里所谓的修改kernel version string并不是真的修改linux的版本号,因为那样会导致非常多的问题(比如一些驱动会不能用,等等)。所以这里修改的仅仅是/proc系统下的version,而从/proc/version中读取kernel version string是一个通常的做法,所以只需要修改这个就可以了。
kernel/fs/proc/version.c
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;
}
seq_printf和printf的功能很类似,可以输出经格式化的字符串。这里的linux_proc_banner参数实际上是一个格式化字符串,它的定义在文件kernel/init/version.c中:
const char linux_proc_banner[] =
"%s version %s"
" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
" (" LINUX_COMPILER ") %s\n";
所以很明显你可以通过修改上面2个文件来定制你自己的version string.
接下来看看Android的setttings中是如何来读取kernel version的:
packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java
public static String getFormattedKernelVersion() {
try {
return formatKernelVersion(readLine(FILENAME_PROC_VERSION));
} catch (IOException e) {
Log.e(LOG_TAG,
"IO Exception when getting kernel version for Device Info screen",
e);
return "Unavailable";
}
}
我们看到Android并不是直接返回从/proc/version中读到的内容,而是经过了formatKernelVersion()方法的处理。否则会返回Unavailable。看一下formatKernelVersion()这个方法:
public static String formatKernelVersion(String rawKernelVersion) {
// Example (see tests for more):
// Linux version 3.0.31-g6fb96c9 ([email protected]) \
// (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: "[email protected]" (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);
if (!m.matches()) {
Log.e(LOG_TAG, "Regex did not match on /proc/version: " + rawKernelVersion);
return "Unavailable";
} else if (m.groupCount() < 4) {
Log.e(LOG_TAG, "Regex match on /proc/version only returned " + m.groupCount()
+ " groups");
return "Unavailable";
}
return m.group(1) + "\n" + // 3.0.31-g6fb96c9
m.group(2) + " " + m.group(3) + "\n" + // [email protected] #1
m.group(4); // Thu Jun 28 11:02:39 PDT 2012
}
呵呵,Android系统对version string做了正则匹配,所以我们不能随意修改version string,必须要保证这里的正则表达式和上一步中修改的version string能正确匹配,否则就会是unavailable.