系統技術非業餘研究 » Erlang網路多程序模型的實驗
阿新 • • 發佈:2018-12-31
在做網路程式的時候我們會經常用到多程序模式. 主程序執行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.
[email protected]:~/otp/test# ls *.erl child.erl test.erl [email protected]:~/otp/test# erlc *.erl
[email protected]:~/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.
[email protected]:~/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).
[email protected]:~/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.