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的版本号也是一致的。
博主你好,请问你编译过3.18的内核吗?我用3.18内核启动5.1 和 6.0 的模拟器都失败了,一直黑屏。我在多个论坛提问了但是一直无人解决。http://www.oschina.net/question/864568_2182561
Hi, 我试了一下,Android版本我使用的是n-preview-2, 做完lunch m_e_arm-eng 之后:
编译kernel使用的命令:
$ ARCH=arm CROSS_COMPILE=arm-linux-androideabi- make goldfish_armv7_defconfig
$ ARCH=arm CROSS_COMPILE=arm-linux-androideabi- make -j 4
执行如下命令lunch android emulator:
$ emulator -show-kernel -kernel /local/kernel-goldfish-3.18-dev/arch/arm/boot/zImage
之后,跟你描述的问题一样。
但是如果在编译kernel时,CROSS_COMPILE设为arm-linux-androidkernel-时,编译出来的kernel可以运行(找不到ramdisk?跟你的问题应该不一样,如果需要,可以一同分析),相关的log如下:
hzak@B85RPI:/data/n-preview-2$ emulator -show-kernel -kernel /local/kernel-goldfish-3.18-dev/arch/arm/boot/zImage -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)
emulator: WARNING: Increasing RAM size to 1GB] (unwind_backtrace) from [] (show_stack+0x10/0x14) ] (show_stack) from [] (panic+0x9c/0x238) ] (panic) from [] (mount_block_root+0x2a0/0x2e8) ] (mount_block_root) from [] (prepare_namespace+0x1b0/0x228) ] (prepare_namespace) from [] (kernel_init_freeable+0x1cc/0x220) ] (kernel_init_freeable) from [] (kernel_init+0x8/0x110) ] (kernel_init) from [] (ret_from_fork+0x14/0x3c)
serial0 console
emulator: UpdateChecker: skipped version check
Uncompressing Linux… done, booting the kernel.
Booting Linux on physical CPU 0x0
Initializing cgroup subsys cpu
Initializing cgroup subsys cpuacct
Linux version 3.18.0-gdfc5f3c (hzak@B85RPI) (gcc version 4.9.x 20150123 (prerelease) (GCC) ) #1 PREEMPT Mon Jun 6 18:49:39 CST 2016
CPU: ARMv7 Processor [410fc080] revision 0 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: Goldfish
Memory policy: Data cache writeback
CPU: All CPU(s) started in SVC mode.
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260624
Kernel command line: qemu.gles=0 qemu=1 console=ttyGF0 android.qemud=ttyGF1 androidboot.hardware=goldfish android.checkjni=1 ndns=1
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 1016176K/1048576K available (4142K kernel code, 104K rwdata, 788K rodata, 239K init, 188K bss, 32400K reserved, 270336K highmem)
Virtual kernel memory layout:
vector : 0xffff0000 – 0xffff1000 ( 4 kB)
fixmap : 0xffc00000 – 0xfff00000 (3072 kB)
vmalloc : 0xf0000000 – 0xff000000 ( 240 MB)
lowmem : 0xc0000000 – 0xef800000 ( 760 MB)
pkmap : 0xbfe00000 – 0xc0000000 ( 2 MB)
.text : 0xc0008000 – 0xc04d8a54 (4931 kB)
.init : 0xc04d9000 – 0xc0514e3c ( 240 kB)
.data : 0xc0516000 – 0xc0530294 ( 105 kB)
.bss : 0xc056f49c – 0xc059e758 ( 189 kB)
Preemptible hierarchical RCU implementation.
NR_IRQS:256
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836480000000ns
Console: colour dummy device 80×30
Calibrating delay loop… 600.47 BogoMIPS (lpj=3002368)
pid_max: default: 32768 minimum: 301
Security Framework initialized
SELinux: Initializing.
Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
Initializing cgroup subsys freezer
Initializing cgroup subsys debug
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0x3efa98 – 0x3efaf0
VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 0
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
Switched to clocksource goldfish_timer
NET: Registered protocol family 2
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP: reno registered
UDP hash table entries: 512 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 512 (order: 1, 8192 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Trying to unpack rootfs image as initramfs…
rootfs image is not initramfs (junk in compressed archive); looks like an initrd
Freeing initrd memory: 1224K (c0800000 – c0932000)
goldfish_new_pdev goldfish_interrupt_controller at ff000000 irq -1
goldfish_new_pdev goldfish_device_bus at ff001000 irq 1
goldfish_new_pdev goldfish_timer at ff003000 irq 3
goldfish_new_pdev goldfish_rtc at ff010000 irq 10
goldfish_new_pdev goldfish_tty at ff002000 irq 4
goldfish_new_pdev goldfish_tty at ff011000 irq 11
goldfish_new_pdev goldfish_tty at ff012000 irq 12
goldfish_new_pdev smc91x at ff013000 irq 13
goldfish_new_pdev goldfish_fb at ff014000 irq 14
goldfish_new_pdev goldfish_audio at ff004000 irq 15
goldfish_new_pdev goldfish-battery at ff015000 irq 16
goldfish_new_pdev goldfish_events at ff016000 irq 17
goldfish_new_pdev goldfish_nand at ff017000 irq -1
goldfish_new_pdev goldfish_pipe at ff018000 irq 18
goldfish_pdev_worker registered goldfish_interrupt_controller
goldfish_pdev_worker registered goldfish_device_bus
goldfish_pdev_worker registered goldfish_timer
goldfish_pdev_worker registered goldfish_rtc
goldfish_pdev_worker registered goldfish_tty
goldfish_pdev_worker registered goldfish_tty
goldfish_pdev_worker registered goldfish_tty
goldfish_pdev_worker registered smc91x
goldfish_pdev_worker registered goldfish_fb
goldfish_pdev_worker registered goldfish_audio
goldfish_pdev_worker registered goldfish-battery
goldfish_pdev_worker registered goldfish_events
goldfish_pdev_worker registered goldfish_nand
goldfish_pdev_worker registered goldfish_pipe
futex hash table entries: 256 (order: -1, 3072 bytes)
audit: initializing netlink subsys (disabled)
audit: type=2000 audit(0.400:1): initialized
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
fuse init (API version 7.23)
msgmni has been set to 1459
bounce: pool size: 64 pages
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
console [ttyGF0] enabled
brd: module loaded
loop: module loaded
nbd: registered device at major 43
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky
smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre
smc91x smc91x.0 eth0: SMC91C11xFD (rev 1) at fe013000 IRQ 13
[nowait]
smc91x smc91x.0 eth0: Ethernet addr: 52:54:00:12:34:56
mousedev: PS/2 mouse device common for all mice
input: qwerty2 as /devices/platform/goldfish_events.0/input/input0
goldfish_rtc goldfish_rtc: rtc core: registered goldfish_rtc as rtc0
device-mapper: uevent: version 1.0.3
device-mapper: ioctl: 4.28.0-ioctl (2014-09-17) initialised: dm-devel@redhat.com
ashmem: initialized
Netfilter messages via NETLINK v0.30.
nf_conntrack version 0.5.0 (15896 buckets, 63584 max)
ctnetlink v0.93: registering with nfnetlink.
xt_time: kernel timezone is -0000
ip_tables: (C) 2000-2006 Netfilter Core Team
arp_tables: (C) 2002 David S. Miller
TCP: cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
sit: IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
NET: Registered protocol family 15
bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
8021q: 802.1Q VLAN Support v1.8
goldfish_rtc goldfish_rtc: setting system clock to 2016-06-06 11:07:40 UTC (1465211260)
RAMDISK: Couldn’t find valid RAM disk image starting at 0.
VFS: Cannot open root device “(null)” or unknown-block(0,0): error -6
Please append a correct “root=” boot option; here are the available partitions:
1f00 563200 mtdblock0 (driver?)
1f01 563200 mtdblock1 (driver?)
1f02 67584 mtdblock2 (driver?)
Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
CPU: 0 PID: 1 Comm: swapper Not tainted 3.18.0-gdfc5f3c #1
[
[
[
[
[
[
[
—[ end Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
我编译时选的是x86的架构,我的android N模拟器也是x86。另外,https://android.googlesource.com/kernel/goldfish.git 这里有两种标签,一种是带goldfish字样的,一种是不带的。如android-3.18 和 android-goldfish-3.18-dev 。两个我都下载了,但是前者的arch/x86(或者arm)/configs/目录下并无goldfish_defconfig ,也就是这个内核并不是为模拟器准备的?可是它们不是都在goldfish.git 这个目录下吗?真搞不懂。。。
另外博主能邮件交流么? 否则我无法收到通知,邮箱我已经填了。
想找个人交流点问题真是好难,博客园 CSDN segmentfault oschina 到处提问,两天了只有10~30的浏览量,无一回答。看雪上面倒是有450+多浏览量,可是无人回答。加qq群问也是没人回答,都在群里水,发段子,,,也是无语了。注册了个xda结果新手不让发帖。。。
1
其实没有这么麻烦哈,其实在prebuilt/qemu-kernel的提交记录里面会提到goldfish中的提交sha1。然后根据这个sha1去goldfish中checkout哈。
比如对于android-7.1.1_r4,git show android-7.1.1_r4得到:
commit ad96539afe082a566efcde8b161aa9e19a2970a8
Author: TreeHugger Robot
Date: Fri Oct 21 00:13:55 2016 +0000
Merge “DO NOT MERGE ANYWHERE Upgrade 3.10 ranchu kernels to 1936fdf” into nyc-mr1-dev
然后这个1936fdf就是goldfish中的commit sh1.
这也是个好方法,我之前确实没想到。多谢〜
我在想我这个方法比较直接,对于只有SDK的会更适用一些,也许在SDK的某个地方,也记录这个sha1 id 。。。
arm-linux-androideabi-ld: internal error in relocate_special_relocatable, at ../../binutils/gold/arm.cc:10401
请问这样的错误是因为什么呀要怎么处理
arm-linux-androideabi-ld: internal error in relocate_special_relocatable, at ../../binutils/gold/arm.cc:10401
scripts/Makefile.build:375: recipe for target ‘arch/arm/kernel/built-in.o’ failed
make[1]: *** [arch/arm/kernel/built-in.o] Error 1
Makefile:945: recipe for target ‘arch/arm/kernel’ failed
make: *** [arch/arm/kernel] Error 2
你用代码树里面的另外一个编译器试试:
ARCH=arm CORSS_COMPILE=prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel- make
1