1. 程式人生 > >uboot系列之-----頂層Makefile分析(一)

uboot系列之-----頂層Makefile分析(一)

這篇主要分析Makefile檔案開頭部分對與一些編譯環境以及編譯路徑等變數的初始化

VERSION = 2010

PATCHLEVEL = 12

SUBLEVEL =

EXTRAVERSION =

ifneq "$(SUBLEVEL)"""

U_BOOT_VERSION =$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

else

U_BOOT_VERSION =$(VERSION).$(PATCHLEVEL)$(EXTRAVERSION)

Endif

U_BOOT_VERSION = 2010.12

TIMESTAMP_FILE =$(obj)include/timestamp_autogenerated.h

VERSION_FILE = $(obj)include/version_autogenerated.h

HOSTARCH := $(shell uname -m | \

sed-e s/i.86/i386/ \

    -e s/sun4u/sparc64/ \

    -e s/arm.*/arm/ \

    -e s/sa110/arm/ \

    -e s/ppc64/powerpc/ \

    -e s/ppc/powerpc/ \

    -e s/macppc/powerpc/\

    -e s/sh.*/sh/)

$(shell uname -m)表示執行uname –mshell命令,他執行的結果是取出機器硬體名(這臺機器是

64位的,所以其得到的結果就是x86-84)。sed –e s/abc/def 的意思是尋找結果裡面是否有’abc’字樣,如果有,就用‘def’字樣將其代替。

所以整條語句的意思就是,取出uname –m的結果,並在其中尋找是否有i.86字樣,如果有就用i386代替,是否有arm.*(*是萬用字元),如果有,就用arm代替……,本臺機的結果是x86-64所以還保持原樣,沒有用其他字元替換,所以HOSTARCH=x86-64

HOSTOS := $(shell uname -s | tr'[:upper:]' '[:lower:]' | \

            sed -e 's/\(cygwin\).*/(cygwin/')

uname –s 表示取出本機作業系統核心名稱,(這臺機器是Linux)tr ‘[:upper:]’’[:lower:]’表示將結果裡面的大寫字元全部換成小寫字元,sed –e‘s/\(Cygwin\).*/Cygwin/’表示尋找結果裡面是否有cygwin.*字元,如果有就用cygwin替換

所以整句話的結果就是HOSTOS = linux(注意第一個字母L被換成了小寫l)

SHELL := $(shell if [ -x "$$BASH" ]; thenecho $$BASH; \

      else if [-x /bin/bash];then echo /bin/bash;\

     else echosh;fi;fi

SHELL if[-x filename]   表示如果這個filename檔案是可執行的,則為真,顯然BASH變數是空的,則SHELL= /bin/bash  就是說shell命令的路徑位於/bin/bash目錄下

export       HOSTARCH HOSTOS SHELL 

表示將這些變數匯出,供別的檔案使用

ifeq (,$(findstring s,$(MAKEFLAGS)))

XECHO = echo

else

XECHO = :

Endif

If$( findstring string,text )表示從text中尋找string字樣,如果找到了則返回text,如果沒找到就返回空,顯然MAKEFLAGS為空,所以 $(findstring s,$(MAKEFLAGS)) 返回為空,if語句為真,XECHO =echo,執行非靜默編譯,否則,執行靜默編譯(靜默編譯的意思就是在編譯時控制檯不列印任何資訊)

ifdef O

ifeq ("$(origin O)", "commandline")

BUILD_DIR := $(O)

endif

endif

這句話表示如果在編譯的命令裡面加入引數O( make O=/tmp).,就把O後面所指定的值賦給變數BUILD_DIR,BUILD_DIR表示uboot的編譯路徑)

ifneq ($(BUILD_DIR),)

saved-output := $(BUILD_DIR)

如果BUILD_DIR不為空,則將BUILD_DIR的值賦給saved-output

$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})

如果BUILD_DIR是一個目錄名稱,就把該目錄創建出來

BUILD_DIR := $(shell cd $(BUILD_DIR) &&/bin/pwd)

$(if $(BUILD_DIR),,$(error output directory"$(saved-output)" does not exist))

Endif

shell命令的意思是先進入到BUILD_DIR目錄,然後呼叫PWD命令顯示當前路徑名,並把當前路徑名賦給BUILD_DIR變數,If語句判斷BUILD_DIR是否存在,如果還為空就顯示錯誤(命令裡面兩個逗號之間表示空)

OBJTREE            :=$(if $(BUILD_DIR),$(BUILD_DIR),$(CURIDR)) //輸出目錄

SRCTREE             :=$(CURDIR) //原始碼目錄

TOPDIR                :=$(SRCTREE)  //頂層目錄

LNDIR                  :=$(OBJTREE) //連線目錄

export        TOPDIR SRCTREE OBJTREE

先看CURIDR變數,這是一個MAKEFILE的內嵌變數,代表當前路徑,為了驗證,可以如下做個測試:

/tmp/test目錄下新建一個Makefile檔案,在裡面新增如下內容:

    all::

               @echo $(CURDIR)

然後在/tmp/test路徑下執行Make命令,顯示的就是/tmp/test

如果定義了BUILD_DIR,就將BUILD_DIR賦給OBJTREE,如果沒有定義,就將CURIDR賦給OBJTREE

……

所以如果編譯時沒有定義編譯路徑,及沒有定義BUILD_DIR,則以上所有變數都是CURDIR,即當前目錄,也就是uboot的頂層目錄

MKCONFIG        :=$(SRCTREE)/mkconfig) 

export MKCONFIG

ifneq ($(OBJTREE),$(SRCTREE))

REMOTE_BUILD  := 1 

export REMOTE_BUILD

endif

如果原始碼目錄與輸出目錄不想等,則置位REMOTE_BUILD變數

ifneq ($(OBJTREE),$(SRCTREE))

obj := $(OBJTREE)/

src := $(SRCTREE)/

else

obj :=

src :=

endif

export obj src

如果原始碼目錄和輸出目錄不想等,則變數objsrc被賦予相應的值,否則,兩變數都為空

SUBDIRS   =tools\

          examples/standalone\

         examples/api

.PHONY : $(SUBDIRS)

SUBIDRS被賦予了三個路徑名稱,並申明SUBIDRS是一個偽目標

這篇主要分析跟編譯和連線庫檔案相關的變數

ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))

……

else # !config.mk

all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin \

$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot \

$(filter-out tools,$(SUBDIRS)) $(TIMESTAMP_FILE) $(VERSION_FILE) \

updater depend dep tags ctags etags cscope $(obj)System.map:

@echo "System not configured - see README" >&2

@ exit 1

tools:

$(MAKE) -C [email protected] all

endif # config.mk

ifeq語句判斷include目錄下是否存在config.mk檔案(通過《uboot系列之-----uboot配置過程詳細分析》一文可知,只有執行了make xxx_config之後,才存在該檔案)。

我們暫時不分析config.mk存在時的情況,因為太長了,先分析config.mk不存在的情況,即else後的語句,該語句把所有的目標都指向了一個依賴,就是打印出錯資訊“System not configured – see README”,然後退出。

接下來看config.mk存在的情況:

all:

sinclude $(obj)include/autoconf.mk.dep

sinclude $(obj)include/autoconf.mk

先看目標all: makefile開始到現在,發現這個all是第一個目標,也就是說當我們執行make命令時,它是預設目標,但是該目標既沒有依賴也沒有規則,那它起到什麼作用呢?接著往下看,sinclude $(obj)include/autoconf.mk.dep,他的意思是包含autoconf.mk.dep檔案,進入到該檔案,發現第一句是:

include/autoconf.mk: include/common.h \,它也是一個目標,並且有很多的依賴

再回到all的作用上來,如果沒有這個all,那麼當我們執行make 時,根據make法則,(它將第一個目標作為他的預設目標),也就是將autoconf.mk作為預設目標,顯然這不是我們想要的結果,(我們執行make是想編譯整個檔案,也就是執行第365行的all: $(ALL)這個規則,而在這裡加上一個看起來“毫無意義”的all,就能達到我們想要的目的,即執行第一個空的all目標後,會跳過autoconf.mk目標,執行下一個all目標)

再來看sinclude sinclude也是包含檔案的關鍵詞,他與include的區別就是使用sinclude時,即使所需要包含的檔案不存在,也不影響makefile的往下執行。

autoconf.mk.depautoconf.mk這兩個檔案是怎麼來的呢,makefile中有如下一段語句,說明了這兩個檔案的來源:

$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h

@$(XECHO) Generating [email protected] ; \

set -e ; \

: Generate the dependancies ; \

$(CC) -x c -DDO_DEPS_ONLY -M $(HOSTCFLAGS) $(CPPFLAGS) \

-MQ $(obj)include/autoconf.mk include/common.h > [email protected]

$(obj)include/autoconf.mk: $(obj)include/config.h

@$(XECHO) Generating [email protected] ; \

set -e ; \

: Extract the config macros ; \

$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \

sed -n -f tools/scripts/define2mk.sed > [email protected] && \

mv [email protected] [email protected]

這段規則沒有完全看明白,望大俠們幫我分析一下

include $(obj)include/config.mk

export       ARCH CPU BOARD VENDOR SOC

包含配置過程中生成的config.mk檔案,並把該檔案中的變數匯出來

ifeq ($(ARCH),arm)

CROSS_COMPILE =/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

Endif

如果ARCH=arm,即體系架構為ARM ,就給變數CROSS_COMPILE賦值,改變數的值代表了交叉編譯器的路徑

include $(TOPDIR)/config.mk

包含頂層目錄下的config.mk檔案

下面開始定義了目標檔案變數(跟ARM無關的這裡就省略沒有列出來)

OBJS  = $(CPUDIR)/start.o

這裡的CPUDIR目錄在頂層目錄的config.mk檔案裡面定義 CPUDIR=arch/$(ARCH)/cpu/$(CPU),對於smdk4412來說 CPUDIR= arch/arm/cpu/armv7

……

OBJS := $(addprefix $(obj),$(OBJS))

在原有OBJS值前面加上一個路徑$(obj)字首,指明絕對路徑,如果$(obj)為空,則OBJS相當於沒變化

下面開始定義了庫檔案變數(跟硬體平臺無關的這裡就省略沒有列出來)

…….

LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \

"board/$(VENDOR)/common/lib$(VENDOR).o"; fi)

LIBS += $(CPUDIR)/lib$(CPU).o

ifdef SOC

LIBS += $(CPUDIR)/$(SOC)/lib$(SOC).o

Endif

對於smdk4412來說,board/Samsung/common/Makefile檔案並不存在,所以第一個賦值無效,接下來的兩個分別為

LIBS+= arch/arm/cpu/armv7/libarmv7.o

LIBS+= arch/arm/cpu/armv7/exynos/libexynos.o

…..

LIBS += arch/$(ARCH)/lib/lib$(ARCH).o

LIBS+= arch/arm/lib/libarm.o

ifeq ($(SOC),exynos)

LIBS += $(CPUDIR)/s5p-common/libs5p-common.o

Endif

LIBS+= arch/arm/cpu/armv7/s5p-common/libs5p-common.o

LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).o

LIBBOARD := $(addprefix $(obj),$(LIBBOARD))

BOARDDIR定義在頂層目錄的config.mk檔案中BOARDDIR = $(VENDOR)/$(BOARD) 對於smdk4412來說

BOARDDIR = Samsung/smdk4212

LIBBOARD = board/samsung/smdk4212/libsmdk4212.o

PLATFORM_LIBGCC = -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) –lgcc

PLATFORM_LIBS += $(PLATFORM_LIBGCC)

export PLATFORM_LIBS

dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`取得交叉編譯器的libgcc.a的絕對路徑

$(CC) = $(CROSS_COMPILE)gcc

$(CFLAGS)定義在config.mk

-L表示編譯時將其後所跟的目錄作為第一個尋找庫檔案的目錄

LDPPFLAGS += \

-include $(TOPDIR)/include/u-boot/u-boot.lds.h \

$(shell $(LD) --version | \

  sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')

$(LD)定義在頂層目錄的config.mk檔案

LD= $(CROSS_COMPILE)ld,表示交叉編譯器裡面的連線工具

shell $(LD) –version表示取得連線工具的版本,我這裡的版本號是GNU ld (GNU Binutils for Ubuntu) 2.22”

ifeq ($(CONFIG_NAND_U_BOOT),y)

NAND_SPL = nand_spl

U_BOOT_NAND = $(obj)u-boot-nand.bin

endif

ifeq ($(CONFIG_ONENAND_U_BOOT),y)

ONENAND_IPL = onenand_ipl

U_BOOT_ONENAND = $(obj)u-boot-onenand.bin

ONENAND_BIN ?= $(obj)onenand_ipl/onenand-ipl-2k.bin

endif

__OBJS := $(subst $(obj),,$(OBJS))

__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))

$subst(<from>,<to>,<text>)的功能是將<text>中的<from>字串換成<to>字串

__OBJS相當於擷取OBJS的相對路徑__LIBS類似

本篇主要分析目標檔案以及相關的依賴檔案

ALL += $(obj)u-boot.srec $(obj)u-boot.bin$(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)

all:             $(ALL)

當用make命令編譯時,執行的就是這個all變數

$(obj)u-boot.hex:         $(obj)u-boot

$(OBJCOPY)${OBJCFLAGS} -O ihex $< [email protected]

Vuboot.hexhex格式的檔案。它的依賴u-boot屬於ELF檔案,OBJCOPYOBJCFLAGS定義在頂層config.mk檔案,

OBJCOPY = $(CROSS_COMPILE)objcopy objcopy命令的作用是將一種格式的檔案拷貝成另外一種格式的檔案。

OBJCFLAGS += --gap-fill=0xff; --gap-fill = 0xffobjcopy的引數,表示在拷貝過程中,用0xff來填充段與段之間的空隙。

整句話的意思就是將u-boot拷貝成u-boot.hex 

$(obj)u-boot.srec:        $(obj)u-boot

$(OBJCOPY)-O srec $< [email protected]

類似的,將u-boot拷貝成u-boot.srec檔案

$(obj)u-boot.bin: $(obj)u-boot

$(OBJCOPY)${OBJCFLAGS} -O binary $< [email protected]

$(BOARD_SIZE_CHECK)

ifeq ($(CONFIG_S5PC210),y)

./mkbl2u-boot.bin bl2.bin 14336

Endif

u-boot拷貝成u-boot.bin檔案,同時執行$(BOARD_SIZE_CHECK),在Makefile前面部分,有如下語句定義了BOARD_SIZE_CHECK

ifneq($(CONFIG_BOARD_SIZE_LIMIT),)

BOARD_SIZE_CHECK=\

         @actual='wc -d [email protected] |awk '{print $$!}';\

         limit=$(CONFIG_BOARD_SIZE_LIMIT);\

        if test $$actual =gt $$limit; then\

                 echo "[email protected] exceeds file size limit:";\

                 echo "limit:$$limit bytes";\

                echo "actual: $$actual bytes";\

                echo "excess:$$((actual-limit))bytes";\

                exit 1;\

        fi

else

BOARD_SIZE_CHECK =

Endif

首先看CONFIG_BOARD_SIZE_LIMIT是否被定義了(是否定義了,在autoconf.mk檔案中檢視,它的意思是規定了檔案大小的上限),如果沒定義,BOARD_SIZE_CHECK為空,如果定義了,就比較目標檔案的實際大小與他的上限大小(CONFIG_BOARD_SIZE_LIMIT的值),如果前者大於後者,就退出,如前者小於後者,則繼續執行。

接著分析上面藍色字型的部分

如果在autoconf.mk中定義了CONFIG_S5PC210 = y,則執行mkbl2命令,這個命令是幹嘛的呢?目前還不清楚

$(obj)u-boot.ldr: $(obj)u-boot

               $(CREATE_LDR_ENV)

               $(LDR)-T $(CONFIG_BFIN_CPU)-c [email protected] $<$(LDR_FLAGS)

               $(BOARD_SIZE_CHECK)

生成u-boot.ldr檔案

$(obj)u-boot.ldr.hex:  $(obj)u-boot.ldr 

                   $(OBJCOPY)${OBJCFLAGS}-O ihex $<[email protected] -I binary

$(obj)u-boot.ldr.srec: $(obj)u-boot.ldr 

                    $(OBJCOPY)${OBJCFLAGS} -O srec $< [email protected] -I binary

生成u-boot.ldr.hexu-boot.ldr.sec檔案

$(obj)u-boot.img:         $(obj)u-boot.bin

                   $(obj)tools/mkimage -A $(ARCH) -T firmware -C none\

                  -a$(CONFIG_SYS_TEXT_BASE) -e 0\

                  -n$(shell sed -n -e 's/.*U_BOOT_VERSION//p'$(VERSION_FILE)|\

                          sed -e 's/''[]*$$/for $(BOARD)board''/' )\

                  -d$<[email protected]

Mkimage是給u-boot.bin增加0x40個位元組大小的頭部資訊的工具,其各個引數的意義如下:

  -A 所支援的體系架構,這裡是arm

  -T  映象型別

  -C none  不壓縮

  -a  指定映像在記憶體中的載入地址,映像下載到記憶體中的時候,要按照這個引數來載入

  -e   指定映像執行的入口地址

  -n   指定映像名稱

  -d   指定生成映像的原始檔

$(obj)u-boot.imx:     $(obj)u-boot.bin 

                   $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage\

                   -e $(CONFIG_SYS_TEXT_BASE) -d $<[email protected]

$(obj)u-boot.kwb:      $(obj)u-boot.bin

                   $(obj)tools/mkimage -n $(CONFIG_SYS_KWD_CONFIG) -T kwbimage\

                   -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) -d $<[email protected]

類似於上面

$(obj)u-boot.dis:$(obj)u-boot

                   $(OBJDUMP) -d $< > [email protected]

通過u-boot檔案生成u-boot.dis  u-boot.disu-boot的反彙編程式碼

GEN_UBOOT = \

                  UNDEF_SYS='$(OBJDUMP) -x $(LIBBOARD) $(LIBS)|\

                 sed -n -e 's/.*\(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'sprt|uniq;\

                 cd $(LDR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS)\

                     --start-group $(__LIBS) --end-group $(P;ATFORM_LIBS)

                        -Map u-boot.map -o u-boot

由連線工具生成u-boot檔案,並生成對映檔案u-boot.map,具體的細節我也沒看很懂

$(obj)u-boot: depend\

                  $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds

                  $(GEN_UBOOT)

這個是ELF格式的u-boot檔案生成規則,後面那些變數都是它的依賴

先看depend

depend dep:     $(TIMESTAMP_FILE) $(VERSION_FILE) \ 

                    $(obj)include/autoconf.mk\

                    $(obj)include/generated/generic -asm-foosets.h

                   for dir in $(SUBDIRS) $(CPUDIR) $(dir $(LDSCRIPT));do\

                               $(MAKE) -C $$ dir _depend;done

依次進入到$(SUBDIRS)$(CPUDIR)$(dir $(LDSCRIPT))目錄,執行make _depend命令。_depend定義在頂層目錄的rules.mk檔案中,總的說來,依賴depend就是在相關的目錄下生成.depend檔案,.depend檔案的內容列出了每個目標檔案的依賴檔案

UBOOT的Makefile至此就大致分析完了,可能還有些地方說的不是很明白,望大家指正,接下來就要分析原始碼了

相關推薦

uboot系列-----頂層Makefile分析

這篇主要分析Makefile檔案開頭部分對與一些編譯環境以及編譯路徑等變數的初始化 VERSION = 2010 PATCHLEVEL = 12 SUBLEVEL = EXTRAVERSION = ifneq "$(SUBLEVEL)""" U_BOOT_VERSION

Docker系列CentOS7安裝Docker

add 程序 發布 更新 介紹 entos star alt ice 0、前言 整體架構目錄:ASP.NET Core分布式項目實戰-目錄 一、瞎扯淡(只講有用的) 感興趣的同學可以上網搜索一下docker具體的介紹。我這邊主要介紹偏實戰的內容,不喜勿噴,有問題也請

linux驅動篇 driver_register 過程分析

linux驅動註冊過程分析--driver_register(一) 個人筆記,歡迎轉載,請註明出處,共同分享 共同進步  http://blog.csdn.net/richard_liujh/article/details/45825333 kernel版本3.10.1

WiresharkFTP協議分析

最近專案需求,需要抓取並還原網路中通過ftp傳輸的檔案。故對ftp協議進行了簡單學習,總結如下。 1. ftp協議概述 這部分內容我參考的百度文庫的一篇文件: 裡面講的很詳細。在此對重點的部分進行總結一下。 1)ftp服務端的用到兩個埠20和21。 2)FTP使

死磕 java同步系列ReentrantLock原始碼解析——公平鎖、非公平鎖

問題 (1)重入鎖是什麼? (2)ReentrantLock如何實現重入鎖? (3)ReentrantLock為什麼預設是非公平模式? (4)ReentrantLock除了可重入還有哪些特性? 簡介 Reentrant = Re + entrant,Re是重複、又、再的意思,entrant是enter的名詞或

ios開發系列記憶體洩漏分析

接上篇,本篇主要講解通知和 KVO 不移除觀察者、block 迴圈引用 、NSThread 和 RunLoop一起使用造成的記憶體洩漏。 1、通知造成的記憶體洩漏 1.1、ios9 以後,一般的通知,都不再需要手動移除觀察者,系統會自動在dealloc 的時候呼叫 [[NSNotificationCenter

Spring Cloud 系列 Config 配置中心

## 服務配置現狀      配置檔案是我們再熟悉不過的,在微服務系統中,每個微服務不僅僅只有程式碼,還需要**連線其他資源**,例如資料庫的配置或功能性的開關 MySQL、Redis 、Security 等相關的配置。除了專案執行的基礎配置之外,還有一些配置是與我們業務有關係的,比如說七牛儲存、簡訊和郵

Spring Cloud 系列 Apollo 配置中心

背景 隨著程式功能的日益複雜,程式的配置日益增多:各種功能的開關、引數的配置、伺服器的地址等等。 對程式配置的期望值也越來越高:配置修改後實時生效,灰度釋出,分環境、分叢集管理配置,完善的許可權、稽核機制等等。 在這樣的大環境下,傳統的通過配置檔案、資料庫等方式已經越來越無法滿足開發人員對配置管理

linux設備驅動misc驅動框架源碼分析

linux驅動開發misc設備驅動 1、misc設備驅動框架源碼部分是由內核開發者實現提供的,主要是創建misc類和為驅動開發者提供misc_register函數,來進行創建misc設備。 這部分的源碼在/drvier/char/misc.c裏,代碼如下:/* * linux/drivers/c

linux驅動開發蜂鳴器驅動源碼分析

linux 蜂鳴器 驅動 蜂鳴器的驅動源碼在/driver/char/buzzer/x210-buzzer.c文件中,源碼如下#include <linux/module.h> #include <linux/kernel.h> #include <linux

Glide原始碼分析從用法來看with方法

繼續啃原始碼,用過Glide的人,肯定都覺得它好好用,我們一般只需要幾行程式碼,就可以達到我們想要的效果,可以在這個背後是什麼呢?就需要我們來看了。 我一般看原始碼,我喜歡先從用法來看,然後一步一步的再細扣,所以就先從用法來看Glide的整體流程。 用過Glide的人,用下面這段

zigbee ZStack-2.5.1a原始碼分析

先看main, 在檔案Zmain.c裡面 main osal_init_system(); osalInitTasks(); ... ... SampleApp_Init( taskID ); // 使用者定義的任務

設計模式綜合例項分析資料庫同步系統

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android編譯系統分析幾個關鍵點

已開通新的部落格,後續文字都會發到新部落格 http://www.0xfree.top Android 編譯系統解析系列文件 解析lunch的執行過程以及make執行過程中include檔案的順序 Android編譯系統分析之lunch分析 Android

omapl138移植uboot系列新增MTD分割槽第七篇

struct mtd_partition mapl138_spiflash_partition[] = {          {                    .name                = "nor0",                    .offs

omapl138移植uboot系列啟動核心原理啟動核心第三篇)

struct tag {          struct tag_header hdr;          union {                    struct tag_core                  core;                

Go學習go-ethereum【以太坊】原始碼分析

關於Go語言環境的安裝與配置,我在《入門篇》進行了詳細講解,有需要的朋友可以前往閱讀,本文進入當下比較火熱的區塊鏈專案 - 以太坊(go-ethereum)進行原始碼解讀。本文內容純屬個人見解,有錯誤理解或者不足之處還請見諒,歡迎一起交流學習。    - 環境準備    -

python資料分析numpy初始化

以下都用numpy的標準“import numpy as np” 1.numpy是同構資料多維容器,同構即資料型別相同 2.初始化: 2.1np.arange([start,] end [, step

linux核心分析--核心中的資料結構雙鏈表

關於核心中使用到的資料結構這一系列會有五篇文章, 分別介紹    連結串列    佇列    雜湊    對映    紅黑樹

Java併發包原始碼學習執行緒池ThreadPoolExecutor原始碼分析

Java中使用執行緒池技術一般都是使用Executors這個工廠類,它提供了非常簡單方法來建立各種型別的執行緒池: public static ExecutorService newFixedThreadPool(int nThreads) public static ExecutorService