Kernel启动时间优化

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 at 0

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尽早可用。

 

你可能感兴趣的:(Kernel)