1、问题描述
Linux的内核用的是3.14版本。UI层跑的是类似Qt的系统。目前Kernel从启动到init进程大概需要3.5秒时间,另外到加载U盘需要7.5秒左右时间。
由于Bootloader执行过程很快,所以不是本次需要优化的目标。
系统原始的Kernel启动部分Log如下:
15:29:01.552: [ 0.000000]Linux version 3.14.19 (gcc version 4.8.3 20140401 (prerelease) (crosstool-NGlinaro-1.13.1-4.8-2014.04 - Linaro GCC 4.8-2014.04) ) #1 SMP Mon Jun 6 14:05:35CST 2016
15:29:01.569: [ 0.000000]CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c53c7d
15:29:01.576: [ 0.000000]CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
15:29:01.588: [ 0.000000]Memory policy: Data cache writealloc
15:29:01.593: [ 0.000000]On node 0 totalpages: 40960
15:29:01.597: [ 0.000000]free_area_init_node: node 0, pgdat c061ba00, node_mem_map c9eba000
15:29:01.604: [ 0.000000] Normal zone: 320 pagesused for memmap
15:29:01.609: [ 0.000000] Normal zone: 0 pagesreserved
15:29:01.613: [ 0.000000] Normal zone: 40960pages, LIFO batch:7
15:29:01.618: [ 0.000000]PERCPU: Embedded 7 pages/cpu @c9eaf000 s7232 r8192 d13248 u32768
15:29:01.625: [ 0.000000]pcpu-alloc: s7232 r8192 d13248 u32768 alloc=8*4096
15:29:01.631: [ 0.000000]pcpu-alloc: [0] 0
15:29:01.634: [ 0.000000]Built 1 zonelists in Zone order, mobility grouping on. Total pages: 40640
15:29:01.642: [ 0.000000]Kernel command line: console=ttyS0,115200n8 rw init=initandroidboot.console=ttyS0 rootfstype=ramfs slram=mtd0,0x20700000,+0x00600000debug user_debug=31blkdevparts=mmcblk0:6M@0x00000000(kernel),1M@0x00600000(dtb),20M@0x00700000(initramfs),512M@0x01b00000(system),512M@0x21b00000(data),-(custom)
15:29:01.669: [ 0.000000]PID hash table entries: 1024 (order: 0, 4096 bytes)
15:29:01.675: [ 0.000000]Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
15:29:01.682: [ 0.000000]Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
15:29:01.783: [ 0.000014]sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 42949672950ns
15:29:01.790: [ 0.000181]Console: colour dummy device 80x30
15:29:01.795: [ 0.000225] Calibrating delay loop... 1386.49 BogoMIPS (lpj=2772992)
15:29:01.801: [ 0.047981]pid_max: default: 32768 minimum: 301
15:29:01.806: [ 0.048168]Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
15:29:01.812: [ 0.048181]Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
15:29:01.819: [ 0.049162]CPU: Testing write buffer coherency: ok
15:29:01.824: [ 0.049414]CPU0: thread -1, cpu 1, socket 0, mpidr 80000001
15:29:01.887: [ 0.127343]bio: create slab
15:29:01.891: [ 0.127863] goldacgpio: registered, base is ca858000
15:29:01.896: [ 0.128298]SCSI subsystem initialized
15:29:01.900: [ 0.128535]usbcore: registered new interface driver usbfs
15:29:01.905: [ 0.128725]usbcore: registered new interface driver hub
15:29:01.910: [ 0.128829]usbcore: registered new device driver usb
15:29:01.915: [ 0.128903]i2c-mn: i/o base 0x9c059100. irq 144
15:29:01.920: [ 0.129380]Advanced Linux Sound Architecture Driver Initialized.
15:29:01.926: [ 0.130559]Switched to clocksource golda_clocksource
15:29:02.039: [ 0.140023]TCP: reno registered
15:29:02.043: [ 0.140043]UDP hash table entries: 256 (order: 1, 8192 bytes)
15:29:02.048: [ 0.140084]UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
15:29:02.055: [ 0.140378]NET: Registered protocol family 1
15:29:02.059: [ 0.140823]RPC: Registered named UNIX socket transport module.
15:29:02.065: [ 0.140836]RPC: Registered udp transport module.
15:29:02.070: [ 0.140844] RPC:Registered tcp transport module.
15:29:02.074: [ 0.140855]RPC: Registered tcp NFSv4.1 backchannel transport module.
15:29:02.081: [ 0.141116]Unpacking initramfs...
15:29:02.084: [ 0.162803]Initramfs unpacking failed: junk in compressed archive
15:29:02.090: [ 0.164955]Freeing initrd memory: 1024K (c7000000 - c7100000)
15:29:02.096: [ 0.165816]futex hash table entries: 256 (order: 2, 16384 bytes)
15:29:02.102: [ 0.175431]squashfs: version 4.0 (2009/01/31) Phillip Lougher
15:29:02.108: [ 0.176294]NFS: Registering the id_resolver key type
15:29:02.113: [ 0.176341]Key type id_resolver registered
15:29:02.117: [ 0.176351]Key type id_legacy registered
15:29:02.121: [ 0.176401]msgmni has been set to 303
15:29:02.125: [ 0.176956] io scheduler noop registered
15:29:02.129: [ 0.176967]io scheduler deadline registered (default)
15:29:02.134: [ 0.177173]Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
15:29:02.140: [ 0.178547] 9c01c200.serial: ttyS0 at MMIO 0x9c01c200 (irq = 133,base_baud = 6250000)
15:29:02.150: [ 0.781481] console [ttyS0] enabled
15:29:02.154: [ 0.785395]CHIPREVST: 0x00000001
15:29:02.157: [ 0.788764] 9c01c300.serial:ttySM0 at MMIO 0x9c01c300 (irq = 135, base_baud = 390625)
15:29:02.170: [ 0.801929]loop: module loaded
15:29:02.174: [ 0.805711]slram: devname = mtd0
15:29:02.200: [ 0.831359]slram: Mapped from 0xcb000000 to 0xcb600000
15:29:02.205: [ 0.836712]smsc911x: Driver version 2008-10-21
15:29:02.210: [ 0.841294] smsc911x smsc911x.0 (unregistered net_device): couldn't getclock -2
15:29:04.311: [ 2.942567] smsc911x smsc911x.0 (unregistered net_device): Device notREADY in 100ms aborting
15:29:04.320: [ 2.951262]usbcore: registered new interface driver cdc_ncm
15:29:04.326: [ 2.957307]ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
15:29:04.333: [ 2.963873] PapajokeEHCI host driver v0333 start
15:29:04.337: [ 2.968749]Enable EHCI Info = 00000000
15:29:04.348: [ 2.978784] papajoke-ehcipapajoke-ehci.0: papajoke EHCI Host Controller
15:29:04.354: [ 2.985762] papajoke-ehcipapajoke-ehci.0: new USB bus registered, assigned bus number 1
15:29:04.363: [ 2.994126] papajoke-ehcipapajoke-ehci.0: irq 159, io mem 0x9c00a000
15:29:04.443: [ 3.074673]usbcore: registered new interface driver usb-storage
15:29:04.449: [ 3.080678]i2c /dev entries driver
15:29:04.595: [ 3.226692]MMC: mmc0 at SDIF1 (irq 156, dma enable, hclk 100000000Hz)
15:29:04.602: [ 3.233221] goldac_mmc_probe:**************initializing wifi_mmc_host***********
15:29:04.703: [ 3.334626]usb 1-1: new high-speed USB device number 2 using papajoke-ehci
15:29:04.755: [ 3.386614]MMC: mmc1 at SDIF0 (irq 154, dma enable, hclk 100000000Hz)
15:29:04.762: [ 3.393429]hidraw: raw HID events driver (C) Jiri Kosina
15:29:04.768: [ 3.399060]usbcore: registered new interface driver usbhid
15:29:04.773: [ 3.404628]usbhid: USB HID core driver
15:29:04.835: [ 3.466824]NET: Registered protocol family 15
15:29:04.840: [ 3.471411]Key type dns_resolver registered
15:29:04.846: [ 3.477051]hub 1-1:1.0: USB hub found
15:29:04.850: [ 3.481215]ALSA device list:
15:29:04.853: [ 3.484273] No soundcards found.
15:29:04.856: [ 3.487777]hub 1-1:1.0: 2 ports detected
15:29:04.861: [ 3.492505]Freeing unused kernel memory: 188K (c05c0000 - c05ef000)
15:29:04.872: [ 3.503441] init (1): /proc/1/oom_adj is deprecated, please use/proc/1/oom_score_adj instead.
15:29:04.916: [ 3.547359]mmc0: BKOPS_EN bit is not set
15:29:04.923: [ 3.554792]#sdif1# : Unknown response type 0x0011(flag=0x0191)
15:29:04.942: [ 3.573849]init: cannot open '/initlogo.rle'
15:29:04.991: [ 3.622648]usb 2-1: new high-speed USB device number 2 using papajoke-ehci
15:29:05.096: [ 3.727444]mmc0: new high speed DDR MMC card at address 0001
15:29:05.102: [ 3.733787]mmcblk0: mmc0:0001 008G30 7.28 GiB
15:29:05.107: [ 3.738611]mmcblk0boot0: mmc0:0001 008G30 partition 1 8.00 MiB
15:29:05.113: [ 3.744884]mmcblk0boot1: mmc0:0001 008G30 partition 2 8.00 MiB
15:29:05.120: [ 3.751459] mmcblk0: p1(kernel)p2(dtb) p3(initramfs) p4(system) p5(data) p6(custom)
15:29:05.132: [ 3.763391] mmcblk0boot1: unknownpartition table
15:29:05.139: [ 3.770450] mmcblk0boot0: unknownpartition table
15:29:05.155: [ 3.786274]EXT4-fs (mmcblk0p4): recovery complete
15:29:05.161: [ 3.792500]EXT4-fs (mmcblk0p4): mounted filesystem with ordered data mode. Opts: (null)
15:29:05.170: [ 3.801939]EXT4-fs (mmcblk0p5): Ignoring removed nomblk_io_submit option
15:29:05.399: [ 4.031060]mmc1: queuing unknown CIS tuple 0x14 (0 bytes)
15:29:05.412: [ 4.043068]usb-storage 2-1:1.0: USB Mass Storage device detected
15:29:05.418: [ 4.049316] papajoke_udcpapajoke_udc.0: Papajoke USB Peripheral Controller
15:29:05.425: [ 4.056579] papajoke_udcpapajoke_udc.0: usb_irq 160, mem caa9c000, DMA
15:29:05.432: [ 4.063366] papajoke_udcpapajoke_udc.0: dma_irq_out 175, dma_irq_in 176
15:29:05.439: [ 4.070231] papajoke_udcpapajoke_udc.0: version: 2014 October
15:29:05.446: [ 4.078041] papajoke_udcpapajoke_udc.1: Papajoke USB Peripheral Controller
15:29:05.454: [ 4.085269] papajoke_udcpapajoke_udc.1: usb_irq 165, mem caab0000, DMA
15:29:05.460: [ 4.092052] papajoke_udcpapajoke_udc.1: dma_irq_out 177, dma_irq_in 178
15:29:05.467: [ 4.098912] papajoke_udcpapajoke_udc.1: version: 2014 October
15:29:05.474: [ 4.105083]scsi0 : usb-storage 2-1:1.0
15:29:05.480: [ 4.111803]scsi 0:0:0:0: Direct-Access Generic-SD/MMC 1.00 PQ: 0 ANSI: 0 CCS
15:29:05.539: [ 4.170233]mmc1: queuing unknown CIS tuple 0x80 (1 bytes)
15:29:05.547: [ 4.178339]mmc1: queuing unknown CIS tuple 0x81 (1 bytes)
15:29:05.553: [ 4.184590]mmc1: queuing unknown CIS tuple 0x82 (1 bytes)
15:29:05.560: [ 4.191855]zero gadget: Gadget Zero, version: Cinco de Mayo 2008
15:29:05.566: [ 4.197990]zero gadget: zero ready
15:29:05.570: [ 4.201487] papajoke_start:found dummy gadget driver
15:29:05.575: [ 4.206615] papajoke_pullup:found dummy gadget driver
15:29:05.580: [ 4.211876]mmc1: new high speed SDIO card at address 0001
15:29:06.885: [ 5.517111]wlan: loading driver v4.2.73.26
15:29:06.890: [ 5.521784]hifDeviceInserted: Dumping clocks (50000000,100000000)
15:29:08.191: [ 6.823323]wlan_logging_sock_activate_svc: Activated wlan_logging svc
15:29:08.198: [ 6.830494]wlan: driver loaded
15:29:08.219: [ 6.851502]TXRX: ol_txrx_peer_find_add_id: Delete Peer c9584800
15:29:08.252: [ 6.884682]init: using deprecated syntax for specifying property'ro.product.manufacturer', use ${name} instead
15:29:08.264: [ 6.895255]init: using deprecated syntax for specifying property 'ro.product.model', use${name} instead
15:29:08.273: [ 6.905276]init: using deprecated syntax for specifying property 'ro.serialno', use${name} instead
15:29:08.288: [ 6.919268]init: Failed to set pid 71 ioprio = 2,2: Function not implemented
15:29:08.657: [ 7.288149] FAT-fs (sda1): Volume was not properly unmounted. Some datamay be corrupt. Please run fsck.
2、节省Loops per jiffies (LPJ)
看了一下Log,这一个时间比较长的操作是以下。
15:29:01.795: [ 0.000225] Calibrating delay loop... 1386.49BogoMIPS (lpj=2772992)
15:29:01.801: [ 0.047981] pid_max: default: 32768 minimum:301
这个好办,在Kernelcommand line中传入参数 lpj=2772992即可解决。
修改device/Golda/board/rootfs_fix/goldac_config_emmc.dtsi文件,bootargs中增加lpj参数,重新编译下载,这一时间就没有了。
3、删除Ethernet驱动
下一个最长时间为:
15:29:02.210: [ 0.841294] smsc911x smsc911x.0 (unregisterednet_device): couldn't get clock -2
15:29:04.311: [ 2.942567] smsc911x smsc911x.0 (unregisterednet_device): Device not READY in 100ms aborting
居然花了两秒时间,查了一下原理图,系统中没有这个芯片,果断去掉。立即Kernel时间不到1.5秒了。
修改linux-golda/arch/arm/configs/goldac_defconfig
-CONFIG_SMSC911X=y
+# CONFIG_SMSC911X is not set
4、调整串口/Console输出
下一个比较长的时间为:
15:29:02.140: [ 0.178547] 9c01c200.serial: ttyS0 at MMIO0x9c01c200 (irq = 133, base_baud = 6250000) is a Papajoke SOCs
15:29:02.150: [ 0.781481] console [ttyS0] enabled
加了很多打印,最后发现,时间消耗在linux-golda/kernel/printk/printk.c中的void register_console(structconsole *newcon)函数。
if (newcon->flags & CON_PRINTBUFFER) {
/*
* console_unlock(); will print out thebuffered messages
* for us.
*/
raw_spin_lock_irqsave(&logbuf_lock,flags);
console_seq= syslog_seq;
console_idx= syslog_idx;
console_prev= syslog_prev;
raw_spin_unlock_irqrestore(&logbuf_lock,flags);
/*
* We're about to replay the log buffer. Only do this to the
* just-registered console to avoid excessivemessage spam to
* the already-registered consoles.
*/
exclusive_console= newcon;
}
这部分代码的功能实际上是把Buffer中的数据通过串口打印出来,因为数据比较多,所以时间长。
最初通过在Kernelcommand line中加入quiet参数,发现在此系统中无用。
那就把CON_PRINTBUFFER标志清掉,找到驱动中设置此位的位置,把它注释掉。这样处理后,之前的打印没没有了,只有从串口初始化之后的打印信息。
修改linux-golda/drivers/tty/serial/8250/8250_core.c及8250_early.c两个文件:
--- a/linux-golda/drivers/tty/serial/8250/8250_core.c
+++ b/linux-golda/drivers/tty/serial/8250/8250_core.c
@@ -2993,7 +2993,7 @@ static struct consoleserial8250_console = {
.device =uart_console_device,
.setup =serial8250_console_setup,
.early_setup = serial8250_console_early_setup,
- .flags = CON_PRINTBUFFER| CON_ANYTIME,
+ .flags =/*CON_PRINTBUFFER | */CON_ANYTIME,
.index = -1,
.data =&serial8250_reg,
};
--- a/linux-golda/drivers/tty/serial/8250/8250_early.c
+++ b/linux-golda/drivers/tty/serial/8250/8250_early.c
@@ -220,7 +220,7 @@ static int __initparse_options(struct early_serial8250_device *device,
static struct console early_serial8250_console__initdata = {
.name = "uart",
.write = early_serial8250_write,
- .flags = CON_PRINTBUFFER |CON_BOOT,
+ .flags = /*CON_PRINTBUFFER |*/CON_BOOT,
.index = -1,
};
5、其它小调整
把Console的初始化数量从63减少到15个。
--- a/linux-golda/include/uapi/linux/vt.h
+++ b/linux-golda/include/uapi/linux/vt.h
@@ -7,8 +7,8 @@
*resizing).
*/
#define MIN_NR_CONSOLES 1 /* must be at least 1 */
-#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */
-#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this*/
+#define MAX_NR_CONSOLES 15 /* serial lines start at 64 */
+#define MAX_NR_USER_CONSOLES 15 /* must be root to allocate above this*/
/* Note: the ioctl VT_GETSTATEdoes not work for
consoles 16 and higher (sinceit returns a short) */
另外,把驱动中打印的调试信息去掉了一些多余的打印。最终的情况,大概Kernel时间为700ms左右。Log显示如下:
21:24:04.755: [ 0.126437]console [ttyS0] enabled
21:24:06.782: [ 0.130426]9c01c300.serial: ttySM0 at MMIO 0x9c01c300 (irq = 135, base_baud = 3125000) isa MN-SIOEXT
21:24:06.796: [ 0.143751]loop: module loaded
21:24:06.799: [ 0.147550]slram: devname = mtd0
21:24:06.803: [ 0.150891]slram: devstart = 0x20700000
21:24:06.807: [ 0.154809]slram: devlength = +0x00600000
21:24:06.811: [ 0.158910]slram: devname=mtd0, devstart=0x20700000, devlength=0x600000
21:24:06.819: [ 0.166844]slram: Registered device mtd0 from 531456KiB to 537600KiB
21:24:06.825: [ 0.173277]slram: Mapped from 0xf0800000 to 0xf0e00000
21:24:06.831: [ 0.178757]usbcore: registered new interface driver cdc_ncm
21:24:06.837: [ 0.184911]ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
21:24:06.851: [ 0.198943] papajoke-ehcipapajoke-ehci.0: papajoke EHCI Host Controller
21:24:06.858: [ 0.205923] papajoke-ehcipapajoke-ehci.0: new USB bus registered, assigned bus number 1
21:24:06.866: [ 0.214294] papajoke-ehcipapajoke-ehci.0: irq 159, io mem 0x9c00a000
21:24:06.883: [ 0.230677] papajoke-ehcipapajoke-ehci.0: USB 2.0 started, EHCI 1.00(v0333)
21:24:06.891: [ 0.238732]hub 1-0:1.0: USB hub found
21:24:06.894: [ 0.242509]hub 1-0:1.0: 1 port detected
21:24:06.899: [ 0.246816] papajoke-ehcipapajoke-ehci.1: papajoke EHCI Host Controller
21:24:06.906: [ 0.253791] papajoke-ehcipapajoke-ehci.1: new USB bus registered, assigned bus number 2
21:24:06.914: [ 0.262172] papajoke-ehcipapajoke-ehci.1: irq 164, io mem 0x9c03a000
21:24:06.931: [ 0.278687] papajoke-ehcipapajoke-ehci.1: USB 2.0 started, EHCI 1.00(v0333)
21:24:06.938: [ 0.286595]hub 2-0:1.0: USB hub found
21:24:06.942: [ 0.290442]hub 2-0:1.0: 1 port detected
21:24:06.947: [ 0.294828]usbcore: registered new interface driver usb-storage
21:24:06.953: [ 0.300832]i2c /dev entries driver
21:24:07.099: [ 0.446789]MMC: mmc0 at SDIF1 (irq 156, dma enable, hclk 100000000Hz)
21:24:07.207: [ 0.554713]usb 1-1: new high-speed USB device number 2 using papajoke-ehci
21:24:07.247: [ 0.594701]MMC: mmc1 at SDIF0 (irq 154, dma enable, hclk 100000000Hz)
21:24:07.253: [ 0.601508]hidraw: raw HID events driver (C) Jiri Kosina
21:24:07.259: [ 0.607054]usbcore: registered new interface driver usbhid
21:24:07.264: [ 0.612621]usbhid: USB HID core driver
21:24:07.269: [ 0.617506]ashmem: initialized
21:24:07.273: [ 0.620875]logger: created 256K log 'log_main'
21:24:07.277: [ 0.625582]logger: created 256K log 'log_events'
21:24:07.282: [ 0.630463]logger: created 256K log 'log_radio'
21:24:07.289: [ 0.637482]logger: created 256K log 'log_system'
21:24:07.295: [ 0.643093]usbcore: registered new interface driver snd-usb-audio
21:24:07.302: [ 0.649896]TCP: cubic registered
21:24:07.305: [ 0.653257]Initializing XFRM netlink socket
21:24:07.310: [ 0.658221]NET: Registered protocol family 10
21:24:07.315: [ 0.663608]sit: IPv6 over IPv4 tunneling driver
21:24:07.321: [ 0.668936]NET: Registered protocol family 17
21:24:07.327: [ 0.674764]NET: Registered protocol family 15
21:24:07.331: [ 0.679438] Key type dns_resolver registered
21:24:07.337: [ 0.684655]ALSA device list:
21:24:07.340: [ 0.687672] No soundcards found.
21:24:07.344: [ 0.691725]Freeing unused kernel memory: 188K (c05b7000 - c05e6000)
21:24:07.355: [ 0.703592]hub 1-1:1.0: USB hub found
21:24:07.361: [ 0.709300]hub 1-1:1.0: 2 ports detected
21:24:07.367: [ 0.715099] init (1): /proc/1/oom_adj is deprecated, please use/proc/1/oom_score_adj instead.
6、增加GPIO测试点
为了能够相对精确的测量时间,决定和之前其它项目一下,增加一个测试点GPIO,通过示波器测量。因为在配置过程中遇到了一些小问题,所以特地记录一下。以备用。
先查了一下原始图,找到一个测试点,GPIO 107。查找PIN脚说明档。
此PIN的默认功能为SFOCK1,功能1为GPIO。
从之前的代码中抄来一段,改写。先查PIN脚功能Register FSEL,GPIO对应的为FSEL13
对应的位为15~12,由于此PIN的默认功能不是GPIO,功能1才是GPIO,所以需要把此4bit设置为0001B,参考代码如下:
//FSEL13
rw32= *(volatile u32*)(vaddr_base + 0x154);
rw32&= 0xffff0fff;
rw32 |= 0x00001000;
*(volatileu32*)(vaddr_base + 0x154) = rw32;
功能选择好后,需要把GPIO使能,配置GPOOE寄存器,GPIO 107对应的是GPOOE3
GPIO107对应的位为第11bit位。参考代码如下:
//GPOOE3
rw32= *(volatile u32*)(vaddr_base + 0x8C);
rw32|= 0x00000800;
*(volatile u32*)(vaddr_base + 0x8C) = rw32;
接下来就是设置输出为高或低电平了,设置GPODATA寄存器,对应的寄存器为GPODATA3:
对应的位也是第11位,参考代码如下:
//GPODATA3
rw32= *(volatile u32*)(vaddr_base + 0x6C);
if(onoff) rw32 |= 0x00000800;
elserw32 &= ~0x00000800;
*(volatile u32*)(vaddr_base + 0x6C) = rw32;
在linux-golda/init/main.c文件的start_kernel函数中,在函数最后rest_init()调用之前把GPIO拉高,在启动init进程之前把它拉低。用示波器测量了一下,时间和打印的相差不大,在700ms左右。波形及测量结果如下:
在此还可以把进入到Console之前的打印全部禁止掉,这样的实测下来,还可以节省约200ms左右时间。启动时间约为460ms左右。
修改linux-golda/kernel/printk/printk.c文件中的call_console_drivers()函数。通过Kernel配置参数CONFIG_KNL_NO_LOG来关闭输出。
--- a/linux-golda/kernel/printk/printk.c
+++ b/linux-golda/kernel/printk/printk.c
@@ -1270,6 +1270,7 @@ static voidcall_console_drivers(int level, const char *text, size_t len)
for_each_console(con) {
if (exclusive_console&& con != exclusive_console)
continue;
+#ifndef CONFIG_KNL_NO_LOG
if (!(con->flags &CON_ENABLED))
continue;
if (!con->write)
@@ -1278,6 +1279,7 @@ static voidcall_console_drivers(int level, const char *text, size_t len)
!(con->flags &CON_ANYTIME))
continue;
con->write(con, text, len);
+#endif
}
}
由于系统中Audio,Wifi、BT等已经是生成.ko文件,在init.rc中insmod方式加载的,所以其它可优化的空间不大了。接下来就需要对init.rc文件进行优化了。
7、init.rc启动调整
还是看之前的Log,发现wlan.ko加载的时间比较长,前后大约花了1.3秒,导致Vold加载U盘的时间被拖后,先做了一个简单测试,把insmod wlan.ko去掉,测试了一下,发现时间从4.2秒减少到1.8秒,非常可观。
确定的问题,那就好办了,另外写一个Trigger,通过prop来触发。
on property:sys.drv.late_init=1
insmod /system/lib/modules/wlan.ko
自定义了一个prop: sys.drv.late_init,等到这个值为1时再加载wlan.ko。那么这个值在哪里设置呢,一开始想还是在init.rc中,写一个later_start 的service,设置这个值,发现虽然延迟了,但不明显,时间减少到3.5秒,还是不行。
service drver_init /bin/setprop sys.drv.late_init 1
class late_start
user root
group root
oneshot
也试着加过sleep x之类的语句,发现不起作用(估计写法有问题,不会用)。既然是需要在Vold加载U盘之后加载,那就在Vold中设置吧,在system/vold/Volumn.cpp的setState ()函数中,判断一下当前状态,设置了这个prop.
--- a/system/vold/Volume.cpp
+++ b/system/vold/Volume.cpp
@@ -199,6 +199,16 @@ voidVolume::setState(int state) {
SLOGD("set property(%s) value(%s)", GOLD_VOLD_PROP,propValue);
property_set(GOLD_VOLD_PROP, propValue);
+ if ( (state == Volume::State_NoMedia) ) {
+ FILE *fp =fopen("/dev/block/sda", "r");
+ if ( NULL == fp ) {
+ property_set("gold.drv.late_init","1");
+ } else {
+ fclose(fp);
+ }
+ } else if (state == Volume::State_Mounted){
+ property_set("gold.drv.late_init","1");
+ }
SLOGD("Over broadcaster all client ");
}
另外,由于init中加载同一class的service是按rc文件中出现的顺序加载的,所以把Vold这个service的位置也尽量向前移,在此改为ueventd之后,其它无关的则向后移,如此修改后从开机到U盘在界面上可用,大概还需要4秒左右时间,没有完成目标。还需要继续优化。另外如果开机以后再插入U盘,界面上可用的速度还是很快的,基本在1秒以内,说明开机时慢可能的原因是当时系统繁忙,引起消息处理被滞后。基于上述考虑,把部分驱动的加载延迟个2秒后再加载。之前直接在init.rc中加sleep无效(知道的兄弟告诉一下),所以就简单粗暴的写了个shell脚本来处理。内容如下:
+++ b/device/Golda/board/loaddrv.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+sleep 2
+setprop gold.drv.late_init 1
device/Golda/board/init.rc修改,把两个加载U盘非必须的驱动移到后面加载,写个Service来执行之前的Shell脚本设置这个prop,如下:
--- a/device/Golda/board/init.rc
+++ b/device/Golda/board/init.rc
@@ -585,9 +585,7 @@ on fs
chmod 0777 /system/lib/ld-2.19-2014.04.so
insmod /system/lib/modules/iscdrv.ko
- insmod /system/lib/modules/golda_pcm.ko
insmod /system/lib/modules/hdcpdrv.ko
- insmod /system/lib/modules/vpu.ko
insmod /system/lib/modules/udc-core.ko
insmod /system/lib/modules/papajoke_udc.ko
insmod /system/lib/modules/configfs.ko
@@ -600,11 +598,21 @@ on fs
#mknod
mknod /dev/isc c 0660 0 isc
- mknod /dev/vpu c 0660 0 vpu
+ #mknod /dev/vpu c 0660 0 vpu
mknod /dev/hdcpdrv c 0660 0 hdcpdrv
+service loaddrv /system/bin/sh/system/bin/loaddrv.sh
+ user root
+ group root
+
+on property:gold.vold_done=1
+ start loaddrv
+
onproperty:gold.drv.late_init=1
+ insmod /system/lib/modules/vpu.ko
+ insmod /system/lib/modules/golda_pcm.ko
insmod /system/lib/modules/wlan.ko
+ mknod /dev/vpu c 0660 0 vpu
Vold中设置的prop改为触发调用loaddrv.sh这个脚本。
--- a/system/vold/Volume.cpp
+++ b/system/vold/Volume.cpp
@@ -202,12 +202,12 @@ voidVolume::setState(int state) {
if ( (state == Volume::State_NoMedia) ) {
FILE *fp = fopen("/dev/block/sda", "r");
if ( NULL == fp ) {
- property_set("gold.drv.late_init", "1");
+ property_set("gold.vold_done", "1");
} else {
fclose(fp);
}
- } else if (state == Volume::State_Mounted) {
- property_set("gold.drv.late_init", "1");
+ } else /* if (state == Volume::State_Mounted) */{
+ property_set("gold.vold_done", "1");
}
SLOGD("Over broadcaster all client ");
}
这样改动后,下载启动,有效果了,U盘终于在3秒内可用了。从Log上看,在Vold加载U盘后,系统大概有2秒没有打印输出,之后才开始加载之后的那几个驱动。
另外,在Log中发现在init中显示了几个错误提示,属于init.rc文件写法不正确或用法已经过时。
15:29:04.872: [ 3.503441] init (1): /proc/1/oom_adj isdeprecated, please use /proc/1/oom_score_adj instead.
15:29:08.252: [ 6.884682] init: using deprecated syntax forspecifying property 'ro.product.manufacturer', use instead
15:29:08.264: [ 6.895255] init: using deprecated syntax forspecifying property 'ro.product.model', use instead
15:29:08.273: [ 6.905276] init: using deprecated syntax forspecifying property 'ro.serialno', use instead
15:29:08.288: [ 6.919268] init: Failed to set pid 71 ioprio= 2,2: Function not implemented
根据提示修改init.rc文件,去除错误提示。减少打印输出,也可以节省一点时间。具体的代码就不列了。
另外,由于本系统不需要显示开机Logo,所以可以把init中显示Logo的代码屏蔽掉。
15:29:04.942: [ 3.573849] init: cannot open '/initlogo.rle'
修改system/core/init/init.c及logo.c两个文件。
--- a/system/core/init/init.c
+++ b/system/core/init/init.c
@@ -685,6 +685,7 @@ static int console_init_action(intnargs, char **args)
have_console = 1;
close(fd);
+#ifndef NO_BOOTLOGO
if( load_565rle_image(INIT_IMAGE_FILE) ) {
fd = open("/dev/tty0", O_WRONLY);
if (fd >= 0) {
@@ -708,6 +709,7 @@ static int console_init_action(intnargs, char **args)
close(fd);
}
}
+#endif /* NO_BOOTLOGO */
return 0;
}
---a/system/core/init/logo.c
+++ b/system/core/init/logo.c
@@ -102,6 +102,7 @@ static intvt_set_mode(int graphics)
return r;
}
+#ifndef NO_BOOTLOGO
/*565RLE image format: [count(2 bytes), rle(2 bytes)] */
intload_565rle_image(char *fn)
@@ -180,3 +181,4 @@ fail_restore_text:
return -1;
}
+#endif /* NO_BOOTLOGO */
经过以上修改,最终从Kernel启动到U盘可用,时间大约在2.5秒左右。达到要求。部分Log见下。时间39.672-37.2≈ 2.472,后面的Log是logcat打印的。
14:59:37.212: [ 0.148010] slram: devname = mtd0
14:59:37.215: [ 0.151351] slram: devstart = 0x20700000
14:59:37.219: [ 0.155266] slram: devlength = +0x00600000
14:59:37.739: [ 0.674907] NET: Registered protocol family15
14:59:37.743: [ 0.679533] Key type dns_resolver registered
14:59:37.748: [ 0.684740] ALSA device list:
14:59:37.751: [ 0.687763] No soundcards found.
14:59:37.756: [ 0.691832] Freeing unused kernel memory:188K (c05b7000 - c05e6000)
14:59:37.762: [ 0.698297] ++++++++ start init ++++++++
14:59:37.767: [ 0.703590] hub 1-1:1.0: USB hub found
14:59:38.007: [ 0.943470] mmcblk0: p1(kernel) p2(dtb) p3(initramfs) p4(system) p5(data) p6(custom)
14:59:38.019: [ 0.955544] mmcblk0boot1: unknown partition table
14:59:38.811: [ 1.747749] sd 0:0:0:0: [sda] Assuming drivecache: write through
14:59:38.818: [ 1.753871] sd 0:0:0:0: [sda] Attached SCSIremovable disk
14:59:38.825: [ 1.760622] FAT-fs (sda1): Volume was notproperly unmounted. Some data may be corrupt. Please run fsck.
14:59:39.664: I/fng ( 85):
14:59:39.666: I/fng( 85): SYS [usb] fung=====>UI
14:59:39.672: I/fng( 85): USB Device status update: USB mounted
14:59:39.677: I/fung ( 85):
一些个人体会
Kernel中加载驱动由于是for循环处理的,所以单线程,如果一个时间很长,其它的只能等待。所以对于时间很长的驱动,尽可能把它做成ko文件,在init.rc 中加载。另外,对于不用的驱动,直接把它从配置中去掉。节省出来的时间是立竿见影的。
lpj,console这些是属于通用的改法,可以适用于几乎所有的Linux平台。
串口打印输出还是相对比较耗时的,所以在最终发布时,尽可能减少非必要的打印输出,极端的情况下,可以把输出全部屏蔽。需要看时,自己通过Console或adb中输入dmesg来查看。
init.rc中,把非必须的service延后加载,或通过prop来触发加载。这虽然属于拆东墙补西墙,但却可以让我们关心的Service尽早可用。