Erlang/OTP 新架構(gòu)移植探索

Erlang是一門適用于開發(fā)大規(guī)脑赴椋可擴(kuò)展實(shí)時(shí)軟件系統(tǒng)的語言,主打 并發(fā)分布式 編程呵扛,在電信、銀行筐带、電商今穿、即時(shí)通信等領(lǐng)域均有應(yīng)用案例。

OTP全稱Open Telecom Platform(開放電信平臺)伦籍,相當(dāng)于Erlang的編譯器工具鏈蓝晒。它提供Erlang程序運(yùn)行的虛擬機(jī),以及類似Python shell的Erlang shell帖鸦。

當(dāng)前版本:OTP 23.0

源碼主要文件:

文件類型 文件數(shù)量(含test) 文件數(shù)量(不含test)
.c 598 426
.h 341 319
.cpp 11 11
.cc 1 1
.S 36 6
.erl 3950 1563
.hrl 310 229
.beam 1313 1250

其中芝薇,.erl是Erlang源文件,hrl是Erlang頭文件作儿,.beam是運(yùn)行于虛擬機(jī)上的目標(biāo)文件洛二。

比起編譯器,OTP更像一個(gè)由C/C++實(shí)現(xiàn)的應(yīng)用系統(tǒng)攻锰。即使在config.guess之外的處理器上也可以直接構(gòu)建晾嘶,只要該平臺具備下列工具。

三方依賴

  • GNU make
  • gcc or clang
  • Perl 5
  • GNU m4(用于支持HiPE娶吞,可使用--disable-hipe選項(xiàng)關(guān)閉)
  • ncurses, termcap, or termlib(可使用--without-termcap選項(xiàng)關(guān)閉)
  • sed
  • GNU autoconf(使用Git時(shí)需要)

以下工具在缺少時(shí)會自動跳過相關(guān)模塊的編譯:

  • OpenSSL 0.9.8(構(gòu)建crypto模塊時(shí)需要)
  • JDK 1.6.0(構(gòu)建jinterface模塊時(shí)需要)
  • flex(構(gòu)建megaco模塊時(shí)需要)
  • wxWidgets 3.0(構(gòu)建wx模塊時(shí)需要)

構(gòu)建文檔時(shí)需要:

  • xsltproc
  • fop

交叉編譯

在構(gòu)建平臺上垒迂,使用--host(運(yùn)行平臺)和--build(構(gòu)建平臺)參數(shù)即可實(shí)現(xiàn)交叉編譯:

$ ./otp_build configure --host=<UNAME_MACHINE>-unknown-linux-gnu --build=guess

不過OTP提供了更方便的配置文件法,配置文件位于xcomp目錄:

$ ls xcomp/
README.md                            erl-xcomp-arm64-android.conf               erl-xcomp-powerpc-dso-linux-gnu.conf  erl-xcomp.conf.template
erl-xcomp-TileraMDE2.0-tilepro.conf  erl-xcomp-armv8-rpi3-linux-gnueabihf.conf  erl-xcomp-powerpc64-bgq-linux.conf
erl-xcomp-arm-android.conf           erl-xcomp-avr32-atmel-linux-gnu.conf       erl-xcomp-vars.sh
erl-xcomp-arm-linux.conf             erl-xcomp-mips-linux.conf                  erl-xcomp-x86_64-saf-linux-gnu.conf

xcomp/erl-xcomp.conf.template文件提供了配置模板妒蛇,基于此創(chuàng)建新架構(gòu)的配置文件erl-xcomp-<UNAME_MACHINE>-linux.conf机断,其中的erl_xcomp_builderl_xcomp_host分別對應(yīng)命令行中的--build--host,在erl_xcomp_configure_flags中配置其他命令行參數(shù)绣夺,使用CC吏奸、CXXLD等選項(xiàng)配置交叉編譯器乐导。參考其他架構(gòu)進(jìn)行配置苦丁。

boostrap配置:

$ ./otp_build configure --xcomp-conf=xcomp/erl-xcomp-<UNAME_MACHINE>-linux.conf

構(gòu)建:

$ ./otp_build boot -a

發(fā)布:

$ ./otp_build release -a <ABSOLUTE_RELEASE_DIR>

<ABSOLUTE_RELEASE_DIR>為以絕對路徑指定的文件夾,如果使用相對路徑物臂,腳本將在lib各個(gè)功能模塊的子目錄下分別創(chuàng)建<RELEASE_DIR>旺拉,唯獨(dú)不在當(dāng)前目錄創(chuàng)建产上,不知意欲何為。

<ABSOLUTE_RELEASE_DIR>拷至運(yùn)行平臺蛾狗,cd進(jìn)去安裝:

$ ./Install [-minimal|-sasl] <ABSOLUTE_INSTALL_DIR>

本地編譯

我們可以直接在運(yùn)行平臺上進(jìn)行編譯:

$ ./configure --build=<UNAME_MACHINE>-unknown-linux-gnu

如果不使用--build晋涣,就需要在各config.guessconfig.sub中逐一添加我們的架構(gòu)。

Hello world!

使用一個(gè)簡單示例驗(yàn)證一下新平臺上的OTP能否正常工作沉桌。

編輯源文件:

$ vi hello.erl
-module(hello). 
-export([main/0]). 

main() ->
    io:format("Hello world!~n"). 

編譯:

$ erlc hello.erl

運(yùn)行:

$ erl -noshell -s hello main -s init stop
Hello world!

架構(gòu)相關(guān)

如上谢鹊,我們不費(fèi)吹灰之力就實(shí)現(xiàn)了OTP到新平臺的「移植」,但其實(shí)OTP源碼并非完全架構(gòu)無關(guān)留凭,以下架構(gòu)相關(guān)部分對OTP的影響待考佃扼。

以mips為例,內(nèi)容包含關(guān)鍵詞的文件共13個(gè):

$ grep -lir mips --exclude-dir=*test*
erts/autoconf/config.guess
erts/autoconf/config.sub
erts/configure
erts/doc/src/notes.xml
erts/emulator/hipe/elf64ppc.x
erts/include/internal/gcc/ethread.h
lib/erl_interface/configure
lib/erl_interface/src/auxdir/config.guess
lib/erl_interface/src/auxdir/config.sub
lib/odbc/configure
lib/wx/autoconf/config.guess
lib/wx/autoconf/config.sub
xcomp/erl-xcomp-mips-linux.conf

名稱包含關(guān)鍵詞的文件僅交叉編譯配置文件1個(gè):

$ find -iname *mips*
./xcomp/erl-xcomp-mips-linux.conf

除了erts/include/internal/gcc/ethread.h中的一處#if defined蔼夜,基本只涉及腳本兼耀、配置、文檔和注釋求冷,少得可憐瘤运。然而,事情沒有那么簡單匠题。

第一處

搜索其他架構(gòu)后發(fā)現(xiàn)拯坟,盡管OTP在主流平臺上通用,但深度適配的只有x86韭山、powerpc郁季、sparc、tilera掠哥,這在定義了多線程巩踏、原子操作、內(nèi)存屏障续搀、讀寫鎖塞琼、自旋鎖等內(nèi)核對象的erts/include/internal目錄中可見一斑:

$ ls erts/include/internal/
README                       erl_misc_utils.h     erts_internal.mk.in  ethr_mutex.h                ethread.mk.in               gcc            ppc32    sparc64  x86_64
erl_errno.h                  erl_printf.h         ethr_atomics.h       ethr_optimized_fallbacks.h  ethread_header_config.h.in  i386           pthread  tile
erl_memory_trace_protocol.h  erl_printf_format.h  ethr_internal.h      ethread.h                   ethread_inline.h            libatomic_ops  sparc32  win

$ cd erts/include/internal/
$ ls gcc i386 ppc32 sparc32 sparc64 tile x86_64
gcc:
ethr_atomic.h  ethr_dw_atomic.h  ethr_membar.h  ethread.h

i386:
atomic.h  ethr_dw_atomic.h  ethr_membar.h  ethread.h  rwlock.h  spinlock.h

ppc32:
atomic.h  ethr_membar.h  ethread.h  rwlock.h  spinlock.h

sparc32:
atomic.h  ethr_membar.h  ethread.h  rwlock.h  spinlock.h

sparc64:
ethread.h

tile:
atomic.h  ethr_membar.h  ethread.h

x86_64:
ethread.h

第二處

此外,erts/emulator/sys/unix中涉及一些操作系統(tǒng)內(nèi)核相關(guān)的定義(以powerpc為例):

$ grep -r powerpc erts/emulator/sys/
erts/emulator/sys/unix/erl_unix_sys.h:#  elif (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__)
erts/emulator/sys/unix/sys_float.c:#elif (defined(__powerpc__) && defined(__linux__)) || (defined(__ppc__) && defined(__DARWIN__))
erts/emulator/sys/unix/sys_float.c:#else /* !(x86 || (sparc && linux) || (powerpc && (linux || darwin))) */
erts/emulator/sys/unix/sys_float.c:#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || ((defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))
erts/emulator/sys/unix/sys_float.c:#elif defined(__linux__) && defined(__powerpc__)
erts/emulator/sys/unix/sys_float.c:#if defined(__powerpc64__)
erts/emulator/sys/unix/sys_float.c:#else  /* !((__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __x86_64__ || __ppc__))) */
erts/emulator/sys/unix/sys_float.c:#endif /* (__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __x86_64__ || __ppc__))) */

第三處

最后還有一塊架構(gòu)相關(guān)的大頭就是HiPE(High-Performance Erlang)禁舷,代碼主要集中在lib/hipeerts/emulator/hipe下:

$ ls lib/hipe/
Makefile  amd64  boot_ebin  doc   flow   info  main  native.mk  ppc       rtl    ssa   tools  vsn.mk
TODO      arm    cerl       ebin  icode  llvm  misc  opt        regalloc  sparc  test  util   x86

$ cd lib/hipe/
$ ls amd64 arm ppc sparc x86
amd64:
Makefile                 hipe_amd64_frame.erl     hipe_amd64_ra.erl           hipe_amd64_ra_postconditions.erl       hipe_amd64_sse2.erl
hipe_amd64_assemble.erl  hipe_amd64_liveness.erl  hipe_amd64_ra_finalise.erl  hipe_amd64_ra_sse2_postconditions.erl  hipe_amd64_subst.erl
hipe_amd64_defuse.erl    hipe_amd64_main.erl      hipe_amd64_ra_ls.erl        hipe_amd64_registers.erl               hipe_amd64_x87.erl
hipe_amd64_encode.erl    hipe_amd64_pp.erl        hipe_amd64_ra_naive.erl     hipe_amd64_spill_restore.erl           hipe_rtl_to_amd64.erl

arm:
Makefile      hipe_arm.hrl           hipe_arm_defuse.erl    hipe_arm_frame.erl         hipe_arm_pp.erl           hipe_arm_ra_ls.erl              hipe_arm_registers.erl
TODO          hipe_arm_assemble.erl  hipe_arm_encode.erl    hipe_arm_liveness_gpr.erl  hipe_arm_ra.erl           hipe_arm_ra_naive.erl           hipe_arm_subst.erl
hipe_arm.erl  hipe_arm_cfg.erl       hipe_arm_finalise.erl  hipe_arm_main.erl          hipe_arm_ra_finalise.erl  hipe_arm_ra_postconditions.erl  hipe_rtl_to_arm.erl

ppc:
Makefile               hipe_ppc_cfg.erl       hipe_ppc_frame.erl         hipe_ppc_main.erl         hipe_ppc_ra_ls.erl                 hipe_ppc_registers.erl
hipe_ppc.erl           hipe_ppc_defuse.erl    hipe_ppc_liveness_all.erl  hipe_ppc_pp.erl           hipe_ppc_ra_naive.erl              hipe_ppc_subst.erl
hipe_ppc.hrl           hipe_ppc_encode.erl    hipe_ppc_liveness_fpr.erl  hipe_ppc_ra.erl           hipe_ppc_ra_postconditions.erl     hipe_rtl_to_ppc.erl
hipe_ppc_assemble.erl  hipe_ppc_finalise.erl  hipe_ppc_liveness_gpr.erl  hipe_ppc_ra_finalise.erl  hipe_ppc_ra_postconditions_fp.erl

sparc:
Makefile                 hipe_sparc_cfg.erl       hipe_sparc_liveness_all.erl  hipe_sparc_ra.erl                 hipe_sparc_ra_postconditions_fp.erl
hipe_rtl_to_sparc.erl    hipe_sparc_defuse.erl    hipe_sparc_liveness_fpr.erl  hipe_sparc_ra_finalise.erl        hipe_sparc_registers.erl
hipe_sparc.erl           hipe_sparc_encode.erl    hipe_sparc_liveness_gpr.erl  hipe_sparc_ra_ls.erl              hipe_sparc_subst.erl
hipe_sparc.hrl           hipe_sparc_finalise.erl  hipe_sparc_main.erl          hipe_sparc_ra_naive.erl
hipe_sparc_assemble.erl  hipe_sparc_frame.erl     hipe_sparc_pp.erl            hipe_sparc_ra_postconditions.erl

x86:
Makefile     hipe_rtl_to_x86.erl    hipe_x86_cfg.erl     hipe_x86_frame.erl     hipe_x86_pp.erl           hipe_x86_ra_naive.erl           hipe_x86_subst.erl
NOTES.OPTIM  hipe_x86.erl           hipe_x86_defuse.erl  hipe_x86_liveness.erl  hipe_x86_ra.erl           hipe_x86_ra_postconditions.erl  hipe_x86_x87.erl
NOTES.RA     hipe_x86.hrl           hipe_x86_encode.erl  hipe_x86_main.erl      hipe_x86_ra_finalise.erl  hipe_x86_registers.erl
TODO         hipe_x86_assemble.erl  hipe_x86_encode.txt  hipe_x86_postpass.erl  hipe_x86_ra_ls.erl        hipe_x86_spill_restore.erl
$ ls erts/emulator/hipe/
TODO                hipe_amd64_primops.h  hipe_bif0.c       hipe_debug.c        hipe_module.h      hipe_ppc_glue.S     hipe_sparc_abi.txt    hipe_x86_abi.txt
elf64ppc.x          hipe_arch.h           hipe_bif0.h       hipe_debug.h        hipe_native_bif.c  hipe_ppc_glue.h     hipe_sparc_asm.m4     hipe_x86_asm.m4
hipe_abi.txt        hipe_arm.c            hipe_bif0.tab     hipe_gbif_list.h    hipe_native_bif.h  hipe_ppc_primops.h  hipe_sparc_bifs.m4    hipe_x86_bifs.m4
hipe_amd64.c        hipe_arm.h            hipe_bif1.c       hipe_gc.c           hipe_ops.tab       hipe_primops.h      hipe_sparc_gc.h       hipe_x86_gc.h
hipe_amd64.h        hipe_arm.tab          hipe_bif1.h       hipe_gc.h           hipe_ppc.c         hipe_process.h      hipe_sparc_glue.S     hipe_x86_glue.S
hipe_amd64.tab      hipe_arm_abi.txt      hipe_bif1.tab     hipe_instrs.tab     hipe_ppc.h         hipe_risc_gc.h      hipe_sparc_glue.h     hipe_x86_glue.h
hipe_amd64_abi.txt  hipe_arm_asm.m4       hipe_bif2.c       hipe_load.c         hipe_ppc.tab       hipe_risc_glue.h    hipe_sparc_primops.h  hipe_x86_primops.h
hipe_amd64_asm.m4   hipe_arm_bifs.m4      hipe_bif2.tab     hipe_load.h         hipe_ppc64.tab     hipe_risc_stack.c   hipe_stack.c          hipe_x86_signal.c
hipe_amd64_bifs.m4  hipe_arm_gc.h         hipe_bif64.c      hipe_mkliterals.c   hipe_ppc_abi.txt   hipe_signal.h       hipe_stack.h          hipe_x86_stack.c
hipe_amd64_gc.h     hipe_arm_glue.S       hipe_bif64.h      hipe_mode_switch.c  hipe_ppc_asm.m4    hipe_sparc.c        hipe_x86.c
hipe_amd64_glue.S   hipe_arm_glue.h       hipe_bif64.tab    hipe_mode_switch.h  hipe_ppc_bifs.m4   hipe_sparc.h        hipe_x86.h
hipe_amd64_glue.h   hipe_arm_primops.h    hipe_bif_list.m4  hipe_module.c       hipe_ppc_gc.h      hipe_sparc.tab      hipe_x86.tab

參考資料



2020年8月27日~9月2日 無錫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市牵咙,隨后出現(xiàn)的幾起案子派近,更是在濱河造成了極大的恐慌,老刑警劉巖洁桌,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渴丸,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谱轨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門戒幔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人土童,你說我怎么就攤上這事诗茎。” “怎么了献汗?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵敢订,是天一觀的道長。 經(jīng)常有香客問我罢吃,道長楚午,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任尿招,我火速辦了婚禮糟袁,結(jié)果婚禮上异赫,老公的妹妹穿的比我還像新娘。我一直安慰自己都哭,他們只是感情好啊易,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布吁伺。 她就那樣靜靜地躺著,像睡著了一般租谈。 火紅的嫁衣襯著肌膚如雪篮奄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天割去,我揣著相機(jī)與錄音窟却,去河邊找鬼。 笑死呻逆,一個(gè)胖子當(dāng)著我的面吹牛夸赫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咖城,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼茬腿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宜雀?” 一聲冷哼從身側(cè)響起切平,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辐董,沒想到半個(gè)月后悴品,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年苔严,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了定枷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邦蜜,死狀恐怖依鸥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情悼沈,我是刑警寧澤贱迟,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站絮供,受9級特大地震影響衣吠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壤靶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一缚俏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贮乳,春花似錦忧换、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至浓恳,卻和暖如春刹缝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颈将。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工梢夯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晴圾。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓颂砸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親疑务。 傳聞我的和親對象是個(gè)殘疾皇子沾凄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345