erlang实例——los简单实现

最近看了《erlang程序设计》,好书,翻译的也不错,两天时间,基本读完(我的习惯总是先快速读完一本书再回过头,一边练习一边翻阅),正试着学习编写erlang的例子。Joe在网上(http://erlang.org/examples/examples-2.0.html)给了一个简单系统(sos)的例子,可惜我太笨,怎么都没跑成功,又缺少专研的韧劲去弄清楚为什么,所以干脆决定自己写一个简单的例子。

 

这个简单的例子的基本思想就是首先,启动一个IO进程负责io的读写工作(体现一切皆进程的思想,并且数据也应该是属于进程的,io就是io进程的私有数据),再启动一个shell负责读写和执行用户的命令(不过,目前的实现只是从标准输入读入输入并显示到标准输出,呵呵,刚起步,以后会慢慢完善)。

 

los的主文件是los.erl,其模块声明如下:

 

-module(los).

-export([

boot/0,

make_scripts/0,

read/0,

write/1 ]).


,比较简单,boot/0函数启动los,read/0、write/1从标准输入输出读写数据;至于make_scripts/0,目前还没用到,从joe的sos拷贝过来的,等研究清楚了启动脚本再考虑使用吧。

 

启动los也很简单,首先启动erl shell,运行los:boot()就完成启动:

 

1> los:boot().

los booted!

los_sh started!

los>

 


1.boot/0的工作就是启动io服务进程,然后启动shell等待用户输入:

 

boot() ->

start_io(),

write("los booted!~n"),

los_sh:run(),

write("los goodbye!~n").


2. start_io例程调用make_global例程来创建服务,其实现如下:

 

 

start_io() ->

make_global(io, fun io_loop/0).

 

 

3. make_global例程实现如下:

 

 

make_global(Name, Fun) ->

    case whereis(Name) of

        undefined ->

            Self = self(),

            Pid = spawn(fun() ->

                               make_global(Self,Name,Fun)

                            end),

            receive

                {Pid, ack} ->

                    Pid

            end;

        Pid ->

            Pid

    end.

 

 

make_global首先判断Name是否已经注册,没有注册,则调用spawn函数新建一个进程,并返回Pid,如果已经注册,直接返回Pid。

 

真正注册进程的例程是make_global/3,其代码如下:

 

 

make_global(Pid, Name, Fun) ->

    case register(Name, self()) of

        {'EXIT', _} ->

            Pid ! {self(), ack};

        _ ->

            Pid ! {self(), ack},

            Fun()

    end.

 

 

4. boot有两个write调用,是los提供的系统级函数。write例程的实现如下:

    

write(Str) ->

{write, Reply} = rpc(io, {write, Str}),

case Reply of 

succeed -> succeed;

_ -> failue

end.

 

  write例程就是调用rpc向io进程发送写的消息和要写的数据,io会将写的状态返回给当前进程,rpc就是向io进程发送消息并返回消息。

 

5. rpc例程的实现如下:

 

 

rpc(Name, Q) -> 

         Name ! {rpc, self(), Q},

         receive     

             {Name, Reply} ->

                 Reply;

             {Name, exit, Why} ->

                 exit(Why)

         end.

 

 

6. los还提供了read函数:

 

 

read() ->

{read, Data} = rpc(io, read),

Data.

read函数将读到的数据传递给调用者。

 

 

呵呵,los还是很简单的,需要注意的大概就是read和write的消息格式。

 

下面是los_sh模块,很简单:

 

 

-module(los_sh).

-export([run/0]).

 

run() ->

los:write("los_sh started!~n"),

loop().

 

loop() ->

Data = los:read(),

case lists:member({Data}, [{"q/n"},{"Q/n"},{"quit/n"},{"Quit/n"}]) of 

true -> los:write("los_sh quit!~n");

false -> los:write(Data),

loop()

end.

 

 

shell就是简单的调用read和write读取和显示用户的输入,这并不是真正意义上的shell,下面正试着编写一些简单的命令,能够在los中运行,对系统做一些文件的操作。

 

一个比较有意思的问题是,如果将模块los_sh的名称改为shell,并编译生成shell.beam,那么启动erl会出现问题,有一个很长的错误列表(我并没有记录错误日志,不过很容易实验)。

 

我猜想erlang的shell会寻找类似shell.beam之类的文件吧,还没有细研究过,有哪位高人知道的,希望不吝赐教。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值