Erlang入门备忘录(2):并行编程

从编译到启动:RV1106嵌入式Linux系统构建的效率优化与深度实践 本文深入探讨RV1106嵌入式Linux系统构建的全流程优化策略,重点提升编译速度和驱动加载效率。通过并行编译配置、内核裁剪、驱动加载优化和硬件辅助加速等实践方法,显著缩短系统构建和启动时间,为嵌入式开发提供实用指导。 阅读详情
 

3.1 进程

-module(tut14).

-export([start/0, say_something/2]).

say_something(What, 0) ->
    done;
say_something(What, Times) ->
    io:format("~p~n", [What]),
    say_something(What, Times - 1).

start() ->
    spawn(tut14, say_something, [hello, 3]),
    spawn(tut14, say_something, [goodbye, 3]).

5> c(tut14).
{ok,tut14}

6> tut14:say_something(hello, 3).
hello
hello
hello
done

3.2 消息传送

-module(tut15).

-export([start/0, ping/2, pong/0]).

ping(0, Pong_PID) ->
    Pong_PID ! finished,
    io:format("ping finished~n", []);

ping(N, Pong_PID) ->
    Pong_PID ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping(N - 1, Pong_PID).

pong() ->
    receive
        finished ->
            io:format("Pong finished~n", []);
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start() ->
    Pong_PID = spawn(tut15, pong, []),
    spawn(tut15, ping, [3, Pong_PID]).

1> c(tut15).
{ok,tut15}

2> tut15: start().
<0.36.0>
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
ping finished
Pong finished

3.3 进程的注册名称

-module(tut16).

-export([start/0, ping/1, pong/0]).

ping(0) ->
    pong ! finished,
    io:format("ping finished~n", []);

ping(N) ->
    pong ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping(N - 1).

pong() ->
    receive
        finished ->
            io:format("Pong finished~n", []);
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start() ->
    register(pong, spawn(tut16, pong, [])),
    spawn(tut16, ping, [3]).

2> c(tut16).
{ok, tut16}

3> tut16:start().
<0.38.0>
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
ping finished
Pong finished

3.4 分布式编程

-module(tut17).

-export([start_ping/1, start_pong/0,  ping/2, pong/0]).

ping(0, Pong_Node) ->
    {pong, Pong_Node} ! finished,
    io:format("ping finished~n", []);

ping(N, Pong_Node) ->
    {pong, Pong_Node} ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping(N - 1, Pong_Node).

pong() ->
    receive
        finished ->
            io:format("Pong finished~n", []);
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start_pong() ->
    register(pong, spawn(tut17, pong, [])).

start_ping(Pong_Node) ->
    spawn(tut17, ping, [3, Pong_Node]).
%%----------------------------------------------

-module(tut18).

-export([start/1,  ping/2, pong/0]).

ping(0, Pong_Node) ->
    {pong, Pong_Node} ! finished,
    io:format("ping finished~n", []);

ping(N, Pong_Node) ->
    {pong, Pong_Node} ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping(N - 1, Pong_Node).

pong() ->
    receive
        finished ->
            io:format("Pong finished~n", []);
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start(Ping_Node) ->
    register(pong, spawn(tut18, pong, [])),
    spawn(Ping_Node, tut18, ping, [3, node()]).

3.5 大型示例

File messenger.erl: 

%%% Message passing utility.  
%%% User interface:
%%% logon(Name)
%%%     One user at a time can log in from each Erlang node in the
%%%     system messenger: and choose a suitable Name. If the Name
%%%     is already logged in at another node or if someone else is
%%%     already logged in at the same node, login will be rejected
%%%     with a suitable error message.
%%% logoff()
%%%     Logs off anybody at at node
%%% message(ToName, Message)
%%%     sends Message to ToName. Error messages if the user of this 
%%%     function is not logged on or if ToName is not logged on at
%%%     any node.
%%%
%%% One node in the network of Erlang nodes runs a server which maintains
%%% data about the logged on users. The server is registered as "messenger"
%%% Each node where there is a user logged on runs a client process registered
%%% as "mess_client" 
%%%
%%% Protocol between the client processes and the server
%%% ----------------------------------------------------
%%% 
%%% To server: {ClientPid, logon, UserName}
%%% Reply {messenger, stop, user_exists_at_other_node} stops the client
%%% Reply {messenger, logged_on} logon was successful
%%%
%%% To server: {ClientPid, logoff}
%%% Reply: {messenger, logged_off}
%%%
%%% To server: {ClientPid, logoff}
%%% Reply: no reply
%%%
%%% To server: {ClientPid, message_to, ToName, Message} send a message
%%% Reply: {messenger, stop, you_are_not_logged_on} stops the client
%%% Reply: {messenger, receiver_not_found} no user with this name logged on
%%% Reply: {messenger, sent} Message has been sent (but no guarantee)
%%%
%%% To client: {message_from, Name, Message},
%%%
%%% Protocol between the "commands" and the client
%%% ----------------------------------------------
%%%
%%% Started: messenger:client(Server_Node, Name)
%%% To client: logoff
%%% To client: {message_to, ToName, Message}
%%%
%%% Configuration: change the server_node() function to return the
%%% name of the node where the messenger server runs

-module(messenger).
-export([start_server/0, server/1, logon/1, logoff/0, message/2, client/2]).

%%% Change the function below to return the name of the node where the
%%% messenger server runs
server_node() ->
    messenger@bill.

%%% This is the server process for the "messenger"
%%% the user list has the format [{ClientPid1, Name1},{ClientPid22, Name2},...]
server(User_List) ->
    receive
        {From, logon, Name} ->
            New_User_List = server_logon(From, Name, User_List),
            server(New_User_List);
        {From, logoff} ->
            New_User_List = server_logoff(From, User_List),
            server(New_User_List);
        {From, message_to, To, Message} ->
            server_transfer(From, To, Message, User_List),
            io:format("list is now: ~p~n", [User_List]),
            server(User_List)
    end.

%%% Start the server
start_server() ->
    register(messenger, spawn(messenger, server, [[]])).


%%% Server adds a new user to the user list
server_logon(From, Name, User_List) ->
    %% check if logged on anywhere else
    case lists:keymember(Name, 2, User_List) of
        true ->
            From ! {messenger, stop, user_exists_at_other_node},  %reject logon
            User_List;
        false ->
            From ! {messenger, logged_on},
            [{From, Name} | User_List]        %add user to the list
    end.

%%% Server deletes a user from the user list
server_logoff(From, User_List) ->
    lists:keydelete(From, 1, User_List).


%%% Server transfers a message between user
server_transfer(From, To, Message, User_List) ->
    %% check that the user is logged on and who he is
    case lists:keysearch(From, 1, User_List) of
        false ->
            From ! {messenger, stop, you_are_not_logged_on};
        {value, {From, Name}} ->
            server_transfer(From, Name, To, Message, User_List)
    end.
%%% If the user exists, send the message
server_transfer(From, Name, To, Message, User_List) ->
    %% Find the receiver and send the message
    case lists:keysearch(To, 2, User_List) of
        false ->
            From ! {messenger, receiver_not_found};
        {value, {ToPid, To}} ->
            ToPid ! {message_from, Name, Message}, 
            From ! {messenger, sent} 
    end.


%%% User Commands
logon(Name) ->
    case whereis(mess_client) of 
        undefined ->
            register(mess_client, 
                     spawn(messenger, client, [server_node(), Name]));
        _ -> already_logged_on
    end.

logoff() ->
    mess_client ! logoff.

message(ToName, Message) ->
    case whereis(mess_client) of % Test if the client is running
        undefined ->
            not_logged_on;
        _ -> mess_client ! {message_to, ToName, Message},
             ok
end.


%%% The client process which runs on each server node
client(Server_Node, Name) ->
    {messenger, Server_Node} ! {self(), logon, Name},
    await_result(),
    client(Server_Node).

client(Server_Node) ->
    receive
        logoff ->
            {messenger, Server_Node} ! {self(), logoff},
            exit(normal);
        {message_to, ToName, Message} ->
            {messenger, Server_Node} ! {self(), message_to, ToName, Message},
            await_result();
        {message_from, FromName, Message} ->
            io:format("Message from ~p: ~p~n", [FromName, Message])
    end,
    client(Server_Node).

%%% wait for a response from the server
await_result() ->
    receive
        {messenger, stop, Why} -> % Stop the client 
            io:format("~p~n", [Why]),
            exit(normal);
        {messenger, What} ->  % Normal response
            io:format("~p~n", [What])
    end.

To use this program you need to: 

configure the server_node() function 
copy the compiled code (messenger.beam) to the directory on each computer where you start Erlang. 
In the following example of use of this program, I have started nodes on four different computers, but if you don't have 

that many machines available on your network, you could start up several nodes on the same machine. 

We start up four Erlang nodes, messenger@super, c1@bilbo, c2@kosken, c3@gollum. 

First we start up a the server at messenger@super: 

(messenger@super)1> messenger:start_server().
true
Now Peter logs on at c1@bilbo: 

(c1@bilbo)1> messenger:logon(peter).
true
logged_on
James logs on at c2@kosken: 

(c2@kosken)1> messenger:logon(james).
true
logged_on
and Fred logs on at c3@gollum: 

(c3@gollum)1> messenger:logon(fred).
true
logged_on
Now Peter sends Fred a message: 

(c1@bilbo)2> messenger:message(fred, "hello").
ok
sent
And Fred receives the message and sends a message to Peter and logs off: 

Message from peter: "hello"
(c3@gollum)2> messenger:message(peter, "go away, I'm busy").
ok
sent
(c3@gollum)3> messenger:logoff().
logoff
James now tries to send a message to Fred: 

(c2@kosken)2> messenger:message(fred, "peter doesn't like you").
ok
receiver_not_found
But this fails as Fred has already logged off. 

First let's look at some of the new concepts we have introduced. 

There are two versions of the server_transfer function, one with four arguments (server_transfer/4) and one with five 

(server_transfer/5). These are regarded by Erlang as two separate functions. 

Note how we write the server function so that it calls itself, server(User_List) and thus creates a loop. The Erlang 

compiler is "clever" and optimizes the code so that this really is a sort of loop and not a proper function call. But 

this only works if there is no code after the call, otherwise the compiler will expect the call to return and make a 

proper function call. This would result in the process getting bigger and bigger for every loop. 

We use functions in the lists module. This is a very useful module and a study of the manual page is recommended (erl -

man lists). lists:keymember(Key,Position,Lists) looks through a list of tuples and looks at Position in each tuple to see 

if it is the same as Key. The first element is position 1. If it finds a tuple where the element at Position is the same 

as Key, it returns true, otherwise false. 

3> lists:keymember(a, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
true
4> lists:keymember(p, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
false
lists:keydelete works in the same way but deletes the first tuple found (if any) and returns the remaining list: 

5> lists:keydelete(a, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
[{x,y,z},{b,b,b},{q,r,s}]
lists:keysearch is like lists:keymember, but it returns {value,Tuple_Found} or the atom false. 

There are a lot more very useful functions in the lists module. 

An Erlang process will (conceptually) run until it does a receive and there is no message which it wants to receive in 

the message queue. I say "conceptually" because the Erlang system shares the CPU time between the active processes in the 

system. 

A process terminates when there is nothing more for it to do, i.e. the last function it calls simply returns and doesn't 

call another function. Another way for a process to terminate is for it to call exit/1. The argument to exit/1 has a 

special meaning which we will look at later. In this example we will do exit(normal) which has the same effect as a 

process running out of functions to call. 

The BIF whereis(RegisteredName) checks if a registered process of name RegisteredName exists and return the pid of the 

process if it does exist or the atom undefined if it does not. 

You should by now be able to understand most of the code above so I'll just go through one case: a message is sent from 

one user to another. 

The first user "sends" the message in the example above by: 

messenger:message(fred, "hello")
After testing that the client process exists: 

whereis(mess_client) 
and a message is sent to mess_client: 

mess_client ! {message_to, fred, "hello"}
The client sends the message to the server by: 

{messenger, messenger@super} ! {self(), message_to, fred, "hello"},
and waits for a reply from the server. 

The server receives this message and calls: 

server_transfer(From, fred, "hello", User_List),
which checks that the pid From is in the User_List: 

lists:keysearch(From, 1, User_List) 
If keysearch returns the atom false, some sort of error has occurred and the server sends back the message: 

From ! {messenger, stop, you_are_not_logged_on}
which is received by the client which in turn does exit(normal) and terminates. If keysearch returns {value,{From,Name}} 

we know that the user is logged on and is his name (peter) is in variable Name. We now call: 

server_transfer(From, peter, fred, "hello", User_List)
Note that as this is server_transfer/5 it is not the same as the previous function server_transfer/4. We do another 

keysearch on User_List to find the pid of the client corresponding to fred: 

lists:keysearch(fred, 2, User_List)
This time we use argument 2 which is the second element in the tuple. If this returns the atom false we know that fred is 

not logged on and we send the message: 

From ! {messenger, receiver_not_found};
which is received by the client, if keysearch returns: 

{value, {ToPid, fred}}
we send the message: 

ToPid ! {message_from, peter, "hello"}, 
to fred's client and the message: 

From ! {messenger, sent} 
to peter's client. 

Fred's client receives the message and prints it: 

{message_from, peter, "hello"} ->
    io:format("Message from ~p: ~p~n", [peter, "hello"])
and peter's client receives the message in the await_result function. 

图像加密与解密(附matlab代码) 详细介绍了三种图像加密解密原理,并基于matlab开发了一套相应系统。 阅读详情

相关推荐

Erlang B公式计算器MFC源码

Erlang B公式计算器 VS2008 MFC界面 带B-s s-a B-a 绘图

Erlang io:format() 函数常用参数

一、常用参数 ~n :输出一个换行符(自动匹配平台标准) ~p :参数打印成为美观 ~s : 输出一个字符串,I/O列表或原子,打印时不带引号 ~w :用标准语法输出erlang的数据类型 ~f :输出浮点数,~.kf输出保留k位小数的浮点数 二、格式型 io:format(~F.P.PadModC) 类型,如 io:format("|~-10.10.+s|", ["abc"]). ...

潘广宇的博客 4406

ErlangB_爱尔兰B公式_通信网络_

利用matlab语言编写爱尔兰B公式,方便计算

erlang格式化输出

io:format的格式化参数。 c 输出多个重复的字符。 1.io:format(”~2c”,”a”). 结果:aa,标识输出字母2次。 2.io:format(”~2.1c”,”a”). 结果:_a,标识输出2个字符,1个是后面跟的字母,另一个位置用空格补充,从左开始,如果是”~-2.1c”是从右侧开始。 s 打印字符串,按手册说只接受list,atom,2进制的结构。 w,p是标准输出,支持...

zhangzhiqiangs的博客 813

[Erlang 0041] 详解io:format

最近遇到几个问题,都是和Erlang Shell输出有关,问题解决了但是追问还要继续下去,后面几篇文章都将围绕这一话题展开;那我们就从io:format("hello world!")开始说起吧. %%代码路径:\erl5.9\lib\stdlib-1.18\src\io.erlformat(Format) -> format(Format, []).format(Format,

坚强2002@CSDN 1944

Erlang基础 - 函数、子句、子句保护式

这个标题的内容就简单多了,直接看用例吧,仍然以 helloworld.erl模块为例。 函数: %% This is a simple Erlang module % Test ... -module(helloworld). -export([pie/0, print/1]). pie() -> 3.14 . print(Msg) -> i

1119

Erlang笔记(03) - format格式输出

afds 举例: afasd

学习,记录,总结 的专栏 767

Erlang入门备忘录(1):单行编程

把“Sequential Programming”翻译成“单行编程”,与“Concurrent Programming”并行编程形成对应比较,比翻译成“顺序编程”要好。对应“并发编程”的是“单发编程”。当然,这样咬文嚼字有些矫情。2.1 The Erlang ShellTo shutdown the Erlang system and the Erlang shell type Control-C

lawme的专栏 2227

Erlang入门备忘录(4):记录和宏

5、记录和宏5.1 把大型例程存为多个文件mess_config.hrl header file for configuration data mess_interface.hrl interface definitions between the client and the messenger user_interface.erl functions for the user interfac

lawme的专栏 1186

Erlang入门备忘录(3):系统可靠性

4、可靠性4.1 超时设定-module(tut19).-export([start_ping/1, start_pong/0,  ping/2, pong/0]).ping(0, Pong_Node) ->    io:format("ping finished~n", []);ping(N, Pong_Node) ->    {pong, Pong_Node} ! {ping, self()}

lawme的专栏 1051

关于erlang的进程池

关于erlang的进程池 博客分类: Erlang我的备忘录 poolboyerlang 有两种情况需要考虑使用进程池管理erlang进程。 一种是普通erlang进程,很便宜,一次可以并行很多(默认32K,当然可以调整vm参数设置更大),但是这不意味着可以无限制的使用,实际上轻松的达到上限是很容易的(想想发明国际象棋的那位向国王请赏的办法,类似的,一个进程开两个,两个再

397

ubuntu下erlang源代码的编译与安装

今天重装了ubuntu系统(ubuntu server),发现开发环境几乎是裸的。再重新编译安装erlang需要一些关键库,去年装过,现在又忘了,记之备查。 当然可以用apt-get直接安装erlang,不过版本有些旧而已,本文说的是如何从源代码编译出一个在ubuntu下可用的erlang。 可以用如下命令察看apt安装erlang所依赖的其它库: sudo apt-get buil...

好记性不如烂博客 1591

安装erlang

yum install zlib-develyum install openssl-develyum install perlyum install cpioyum install expat-develyum install gettext-devel 接下来,如果你已经安装过Curl了,那么跳过这一步,没有的话,就装一下. wget http://curl.haxx....

weixin_34377065的博客 256

Erlang边读边练(1)

我看书有个习惯,先看图和代码,然后代码中不懂的再去前后文去找说明,有人说这太浪费时间了,我觉得这样才0距离接触代码。Armstrong的代码看得我十分的不爽,可是,学erlang就是像受戒律一样,忍啊忍,悟啊悟,之后,如修炼得道般豁然开朗。 ok,废话少说,读programming erlang 读到 IRC Lite的时候发现在自己面前横着一道槛了。io_widget是什么?lib_chan是什...

vivimusing的专栏 201

RabbitMQ 运维备忘录(一)

消息队列中间件(Message Queue Middleware,简称为 MQ)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。

小鲸鱼大梦想 1081

RabbitMQ备忘录

Rabbit安装备忘录   整理开发笔记: 由于项目一直比较紧张,在使用的过程中,往往是未做任何笔记 最近有点小空,抽点时间整理记录下。。。。。。。。。     目录        RabbitMQ备忘录一           1安装准备 CentOS_6.5 Python2.7 Jdk1.7 在安装之前,需要先要安装一些其他的软件,否则在安装中间会出现一些...

yuzhi2217的专栏 407

erlang常见基础

每一个文件通常称为一个模块(module),需要特别注意的是在这一行末尾的”.”,这个是不可或缺的。每一个模块的名称必须和它的文件名一样 注意这里的结尾是”;”,表明这个方法还没有结束 在函数中的参数”N,X,Y”我们称之为变量。变量的首字母需要大写 常量是Erlang的另一种数据类型。常量以小写字母开头 常量就是一个简单的名字,不像变量一样拥有值。 在Erl

mt4836的博客 721

Erlang字符串格式化

io_lib:format的格式化参数 ~c 输出字符 输出字符 1> io_lib:format("~c", "a"). ["a"] 输出字符两遍 2> io_lib:format("~2c", "a"). ["aa"] 输出字符串长度为2 , 不足左边补空格 3> io_lib:format("~2.1c", "a"). [[" ",97]] %" a" 输出字符串长度为2 , 不

EnskDeCode 3268

Erlang笔记(06) - 输入输出

io:get_line("").io:get_chars().

学习,记录,总结 的专栏 1694

erlang io:format 远程打印信息

-module(test). -compile([export_all]). r() -> io:format("group leader:~p~n", [erlang:group_leader()]), io:format("node:~p~n", [node()]), erlang:group_leader(whereis(user), self()), io:for

taitoubiyan1的专栏 1295

内窥镜图像的细节增强和亮度增强算法

内窥镜图像的细节增强和亮度增强算法,适用于胃部图像处理(Endoscopic image detail enhancement and brightness enhancement algorithm for stomach image processing)

上一篇: Erlang入门备忘录(1):单行编程
下一篇: Erlang入门备忘录(3):系统可靠性
lawme
博客等级 码龄23年 442粉丝 99原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值