Erlang应用程序启动事件序列

要了解Erlang Application中文件和模块是如何使用的,就必须知道启动一个Application时所发生的事件。

文件组织结构

假设有如下的文件组织结构:

server1.erl
server2.erl
event_handler.erl
example_sup.erl
example_app.erl
example.app
elog.config

启动序列

1. 启动系统

$ erl -boot start_sasl -config elog.config
1> application:start(example).

Erlang应用程序控制器会在example.app中寻找一个{mod, …}声明。它包含应用程序控制器的名称,这里假设为example_app

2. Application回调

example_app:start/2被调用。

3. 启动监控器

example_app:start/2中将调用example_sup:start_link/2启动example监控器

4. Supervisor回调

example_sup:init/1被回调,做一些初始化操作,例如安装错误处理器,然后返回一个监控规范。这个监控规范说明了如何去启动工作进程,例如server1server2

5. 启动工作进程

example监控器根据监控规范逐一启动相应工作进程。

6. 停止系统

2> application:stop(example). % or init:stop().

使用init:stop()关闭系统,所有运行中的应用程序会按顺序一一关闭。


一个编译Erlang的Makefile模板

这是一个简单的编译Erlang的Makefile模板,仅供参考。

# leave these lines alone
.SUFFIXES: .erl .beam .yrl

.erl.beam:
    erlc -W $<
.yrl.erl:
    erlc -W $<

ERL = erl -boot start_clean 

# Here's a list of the erlang modules you want compiling
# If the modules don't fit onto one line add a \ character 
# to the end of the line and continue on the next line

# Edit the lines below
MODS = module1 module2 \
       module3 ... special1 ...\
       ...
       moduleN

# The first target in any makefile is the default target.
# If you just type "make" then "make all" is assumed (because
#   "all" is the first target in this makefile)

all: compile

compile: ${MODS:%=%.beam} subdirs
	
## special compilation requirements are added here

special1.beam: special1.erl    
    ${ERL} -Dflag1 -W0 special1.erl

## run an application from the makefile

application1: compile
	${ERL} -pa Dir1  -s application1 start Arg1 Arg2 

# the subdirs target compiles any code in 
# sub-directories

subdirs:
    cd dir1; $(MAKE)
    cd dir2; $(MAKE)
    ...

# remove all the code

clean:	
    rm -rf *.beam erl_crash.dump
    cd dir1; $(MAKE) clean
    cd dir2; $(MAKE) clean

Erlang二进制操作

二进制型是一种十分节省空间的保存大批量数据的方式,并且Erlang虚拟机对其做了优化,十分高效。

位语法

<<>>
<<E1, E2, ..., En>>

% 每个Ei元素都标示出二进制型或位串的一个片段。单个Ei元素可以有4种形式。

Ei = Value |
     Value:Size |
     Value/TypeSpecifierList |
     Value:Size/TypeSpecifierList

如果表达式的总位数是8的整数倍,就会构建一个二进制型, 否则构建一个位串。

Value 必须是已绑定变量,字符串,或是能得出整数,浮点数或二进制型的表达式。

Size 必须是整数,默认值取决于不同的数据类型,整数8,浮点数64,二进制型则是就二进制型的大小。

TypeSpecifierList 类型指定列表,形式为End-Sign-Type-Unit。任何被省略项,取其默认值。

  • End 字节顺序,可为big | little | native,默认big。
  • Sign 用于模式匹配,可为signed | unsigned,默认unsigned。
  • Type 可为integer | float | binary | bytes | bitstring | bits | utf8 | utf16 | utf32,默认integer。
  • Unit 写法unit:1|2|…256,integer,float,bitstring默认为1,binary默认为8。utf8,utf6和utf32无需提供值。

一个片段的总长度是Size x Unit字节。binary类型的片段长度必须是8的整数倍。

操作示例

二进制型字节反转

byte_reverse(Bin) when is_binary(Bin) ->
    Size = bit_size(Bin),
    <<TBin:Size>> = Bin,
    <<TBin:Size/little>>.

二进制型位反转

bit_reverse(Bin) when is_binary(Bin) ->
    bit_reverse(Bin, <<>>).

bit_reverse(<<>>, RBin) -> RBin;
bit_reverse(Bin, RBin) ->
    <<B:1, C/bitstring>> = Bin, 
    bit_reverse(C, <<B:1, RBin/bitstring>>).

解包IPv4数据报头

-define(IP_VERSION, 4).
-define(IP_MIN_HDR_LEN, 5).

...
DgramSize = byte_size(Dgram),
case Dgram of
    <<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
      ID:16, Flags:3, FragOff:13, TTL:8, Proto:8,
      HdrChkSum:16, SrcIP:32, DestIP:32,
      RestDgram/binary>> when HLen >= 5, 4*HLen =< DgramSize ->
          OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
          <<Opts:OptsLen/binary, Data/binary>> = RestDgram,
          ...

总结

在大多数编程语言里,最小可寻址存储单元的宽度通常是8位。而Erlang最小可寻址存储单元是1位,无需任何位移和掩码操作,依靠威力强大的模式匹配即可轻松完成位级别操作。


在Linux上安装Erlang

依赖

必要

sudo apt-get install build-essential libncurses5-dev openssl libssl-dev

可选

sudo apt-get install fop xsltproc unixodbc-dev libwxgtk3.0-dev freeglut3-dev

编译安装

./configure
make
sudo make install