Menu Home

How to change Kernel Version String

OS: 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.

Categories: android framework linux kernel

Tagged as:

lnmcc

Leave a Reply

Your email address will not be published.