Erlang网络多进程模型的实验
April 7th, 2010
Comments off
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: Erlang网络多进程模型的实验
在做网络程序的时候我们会经常用到多进程模式. 主进程执行bind调用得到句柄后, 同时fork N个子进程, 把句柄传递给子进程, 多进程同时accept来处理.
这个模型在erlang下很有现实意义的. 在之前的测试中,我们演示了erlang的单处理器模式的威力,最多的时候在单cpu上可以发起40,000个tcp广播包.
但是erlang如何利用这个能力呢? 其实Erlang的port也是靠fork来实现的, 是支持这个能力的, 只不过官方的版本会在fork的时候, 把继承过来的句柄全部关闭.
让我们crack下代码来绕过这个问题.
erts/emulator/sys/unix/sys.c
1513 if(0) /*/*fork路径*/*/ 1514 for (i = opts->use_stdio ? 3 : 5; i < max_files; i++) 1515 (void) close(i); ... 1581 fprintf(stderr, "cracked\n"); /*vfork路径*/ 1582 sprintf(fd_close_range, "%d:%d", opts->use_stdio ? 3 : 5, opts->use_stdio ? 3 : 5);
记得重新make && make install
我们下面的代码演示在主进程把一个tcp句柄传递过去, 然后在子进程中恢复成gen_tcp.
root@nd-desktop:~/otp/test# ls *.erl child.erl test.erl root@ubuntu:~/otp/test# erlc *.erl
root@nd-desktop:~/otp/test# cat test.erl
-module(test).
-export([start/0]).
start()->
process_flag(trap_exit, true),
{ok, Sock} = gen_tcp:listen(0, []),
{ok, Handle} = inet:getfd(Sock),
Command ="erl -noshell -s child -handle " ++ integer_to_list(Handle),
io:format("child command line: ~p~n", [Command]),
Child = case (catch open_port({spawn, Command}, [in, {line, 256}])) of
{'EXIT', Reason}->
io:format("open child error, reason: ~p~n", [Reason]),
halt(1);
Port-> Port
end,
register(?MODULE, self()),
io:format("STOP ME: test!stop. ~n",[]),
loop(Child),
io:format("bye~n",[]).
loop(Child)->
receive
{Child, {data, Result}} ->
io:format("child say: ~p~n", [Result]),
loop(Child);
stop->
halt(0);
Other->
io:format("got msg: ~p~n", [Other]),
loop(Child)
end.
root@nd-desktop:~/otp/test# cat child.erl
-module(child).
-export([start/0]).
start()->
{ok, [[HandleArg|_]|_]} = init:get_argument(handle),
Handle = list_to_integer(HandleArg),
io:format("handle: ~w~n", [Handle]),
case gen_tcp:fdopen(Handle, []) of
{ok, Socket} ->
io:format("got socket ok: ~p~n", [Socket]);
_ ->
io:format("got socket fail~n", [])
end,
halt(0).
root@ubuntu:~/otp/test# erl -noshell -s test
child command line: "erl -noshell -s child -handle 8"
cracked
STOP ME: test!stop.
child say: {eol,"handle: 8"}
child say: {eol,"got socket ok: #Port<0.354>"}
got msg: {'EXIT',#Port<0.360>,normal}
^C
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
Bingo! 成功实现目的!
这里给大家一个思路就是说明fork是可行的, 如果你有这个需求把上面的fork patch做好点就行.
Post Footer automatically generated by wp-posturl plugin for wordpress.
Recent Comments