小伙伴们的智能之旅

Android: 编译与emulator相同版本号的kernel – zImage

Android emulator所使用的kernel都是预先编译好的,存放在prebuilts/qemu-kernel/arm/kernel-qemu-armv7。如果需要做kernel方面的开发,如添加新的驱动,使用upstream的kernel等。必竟在emulator中开发要比在开发板上要方便很多。

重新编译kernel时,我们需要有kernel的代码,版本号以及配置文件:

代码可以从这里下载:

git clone https://android.googlesource.com/kernel/goldfish

版本号怎么获取到呢?我们可以看到在android.googlesource.com/kernel/goldfish中有如下分支:

master, android-3.10, android-3.18, android-3.4, android-goldfish-2.6.29等等,那么哪一个是我们所需要的版本号呢?我们可以从开机时的log中看到,所以,我们需要整个项目(笨方法?)

google android设备都是以鱼的名字命名,如Nexus4 – mako, Nexus5 – hammerhead。kernel的命名也是一样:goldfish, ranchu。

主机使用x86平台,系统为ubuntu-14.04 x86_64

代码选用的是android-5.1.1_r15, 当然,你也可以选择更高版本的代码,如android-6.0.1_r7或者是主分支上面的代码:

$ mkdir -pv /local/android-5.1.1_r15 && cd /local/android-5.1.1_r15
$ curl https://storage.googleapis.com/git-repo-downloads/repo > repo
$ chmod a+x repo
$ ./repo init -u https://android.googlesource.com/platform/manifest -b android-5.1.1_r15
$ ./repo sync
$ . build/envsetup.sh
$ lunch m_e_arm-userdebug
$ make -j 4

运行emulator,从开机log中获取:

$ emulator -show-kernel -no-window
emulator: WARNING: system partition size adjusted to match image file (550 MB > 200 MB)

emulator: WARNING: data partition size adjusted to match image file (550 MB > 200 MB)

Creating filesystem with parameters:
    Size: 69206016
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 4224
    Inode size: 256
    Journal blocks: 1024
    Label: 
    Blocks: 16896
    Block groups: 1
    Reserved block group size: 7
Created filesystem with 11/4224 inodes and 1302/16896 blocks
Failed to Initialize backend EGL display
Could not initialize emulated framebufferemulator: WARNING: Could not initialize OpenglES emulation, using software renderer.
serial0 console
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0
Initializing cgroup subsys cpu
Linux version 3.4.67-01422-gd3ffcc7-dirty (digit@tyrion.par.corp.google.com) (gcc version 4.8 (GCC) ) #1 PREEMPT Tue Sep 16 19:34:06 CEST 2014
CPU: ARMv7 Processor [410fc080] revision 0 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: Goldfish
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 130048
Kernel command line: qemu.gles=0 qemu=1 console=ttyS0 android.qemud=ttyS1 android.checkjni=1 ndns=1
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 512MB = 512MB total
Memory: 496568k/496568k available, 27720k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xe0800000 - 0xff000000   ( 488 MB)
    lowmem  : 0xc0000000 - 0xe0000000   ( 512 MB)
      .text : 0xc0008000 - 0xc0450618   (4386 kB)
      .init : 0xc0451000 - 0xc0476000   ( 148 kB)
      .data : 0xc0476000 - 0xc04af9c8   ( 231 kB)
       .bss : 0xc04afa08 - 0xc05f9cb0   (1321 kB)
NR_IRQS:256

可以看到Linux version为3.4.67-01422-gd3ffcc7-dirty, 其中-g代表的是git?而后面7个字符对应的就是在git库中的版本号。所以我们clone完git库,就可以将这个版本给checkout出来:

git clone https://android.googlesource.com/kernel/goldfish
$ git checkout d3ffcc7
Checking out files: 100% (38890/38890), done.
Note: checking out 'd3ffcc7'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at d3ffcc7... MIPS: Refactor 'clear_page' and 'copy_page' functions.

NOTE: 生成Linux version的脚本文件在scripts/setlocalversion中:

scm_version()
{
    local short
    short=false

    cd "$srctree"
    if test -e .scmversion; then
        cat .scmversion
        return
    fi
    if test "$1" = "--short"; then
        short=true
    fi

    # Check for git and a git repo.
    if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then

        # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
        # it, because this version is defined in the top level Makefile.
        if [ -z "`git describe --exact-match 2>/dev/null`" ]; then

            # If only the short version is requested, don't bother
            # running further git commands
            if $short; then
                echo "+"
                return
            fi
            # If we are past a tagged commit (like
            # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
            if atag="`git describe 2>/dev/null`"; then
                echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'

            # If we don't have a tag at all we print -g{commitish}.
            else
                printf '%s%s' -g $head
            fi
        fi
        // ...
}

要获取配置文件,我们要让emulator运行起来,再获取emulator中的/proc/config.gz配置文件:

$ emulator -show-kernel

等emulator运行之后,从另外一个终端获取:

/local/android-5.1.1_r15/kernel $ adb pull /proc/config.gz
$ gunzip config.gz && mv config .config
hzak@B85RPI:/local/android-5.1.1_r15/kernel $ ARCH=arm CORSS_COMPILE=arm-linux-androideabi- make -j 4

之后,我们就可以在arch/arm/boot/下获取我们所需要的kernel – zImage

hzak@B85RPI:/local/android-5.1.1_r15$ emulator -show-kernel -no-window -kernel kernel/arch/arm/boot/zImage 
emulator: WARNING: system partition size adjusted to match image file (550 MB > 200 MB)

emulator: WARNING: data partition size adjusted to match image file (550 MB > 200 MB)

Failed to Initialize backend EGL display
Could not initialize emulated framebufferemulator: WARNING: Could not initialize OpenglES emulation, using software renderer.
serial0 console
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0
Initializing cgroup subsys cpu
Linux version 3.4.67-gd3ffcc7 (hzak@B85RPI) (gcc version 4.8 (GCC) ) #1 PREEMPT Thu Mar 10 08:17:43 EST 2016
CPU: ARMv7 Processor [410fc080] revision 0 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: Goldfish
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 130048
Kernel command line: qemu.gles=0 qemu=1 console=ttyS0 android.qemud=ttyS1 android.checkjni=1 ndns=1
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 512MB = 512MB total
Memory: 496360k/496360k available, 27928k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xe0800000 - 0xff000000   ( 488 MB)
    lowmem  : 0xc0000000 - 0xe0000000   ( 512 MB)
      .text : 0xc0008000 - 0xc0467488   (4478 kB)
      .init : 0xc0468000 - 0xc0493000   ( 172 kB)
      .data : 0xc0494000 - 0xc04aaf08   (  92 kB)
       .bss : 0xc04e3218 - 0xc062d4b0   (1321 kB)
NR_IRQS:256

可见kenrel版本号已经变成了我们编译时生成的版本号了,并且git的版本号也是一致的。