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
- 编译生成所需要image:
$ make -j 4
- 获取kernel的版本号:
运行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
// ...
}
- 获取kernel配置文件
要获取配置文件,我们要让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
- 从代码编译kernel
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的版本号也是一致的。