Archive

Archive for October, 2009

用systemtap来修改下linux内核变量的值

October 29th, 2009 5 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 用systemtap来修改下linux内核变量的值

我们在探索linux内核的时候,经常需要调整下变量的值,看它对系统的影响。如果这个值没有透过/proc来修改的话,那只能编译内核。这个步骤是非常繁琐的。现在我们有systemtap这个利器来帮忙了。

演示如下:
我们通过修改过
extern int sysctl_tcp_fin_timeout;的值来达到目的。是因为这个值是proc导出的 我们好验证是否成功。

root@localhost ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout
15000
[root@localhost ~]# cat test.stp
probe begin
{
        printf("ready go\n");
}

probe kernel.function("do_tcp_setsockopt")
{
        $sysctl_tcp_fin_timeout = $1
        printf("sysctl_tcp_fin_timeout = %d\n", $sysctl_tcp_fin_timeout);
        exit()
}

[root@localhost ~]# stap -g test.stp 18000
ready go

这个时候 stap在运行, 只是还没有触发do_tcp_setsockopt.
现在我们来触发

[root@localhost ~]# erl
Erlang R13B02 (erts-5.7.3)  [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.3  (abort with ^G)
1> {ok, LSock} = gen_tcp:listen(0, []).
{ok,#Port<0.437>}
2>
2> inet:setopts(LSock, [{nodelay,true}]).
ok
3>

Ok,这时候回头可以看到stap打出来以下:
sysctl_tcp_fin_timeout = 18000

我们来验证下:

root@localhost ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout
18000

OK,成功。

Tips:
1. stap对全局变量的写需要-g guru模式。
2. 全局变量必须在一个单元内的函数里面才可以修改, 而且必须是在内核上下文。

PS. 这样写的话会更好,因为这个变量是单元可见的,这个模块里面的任何函数被触发都可以看到这个变量. 因为这是tcp的核心模块随时都会被出发的,免除了以上的麻烦!

$ cat test.stp
probe begin
{
        printf("ready go\n");
}
probe kernel.function("*@net/ipv4/tcp.c") 
//probe kernel.function("do_tcp_setsockopt")
{
        $sysctl_tcp_fin_timeout = $1
        printf("sysctl_tcp_fin_timeout = %d\n", $sysctl_tcp_fin_timeout);
        exit()
}

Post Footer automatically generated by wp-posturl plugin for wordpress.

Erlang如何查看gen_server系列的状态 (高级)

October 29th, 2009 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang如何查看gen_server系列的状态 (高级)

gen_server在erlang otp编程中的地位是无可撼动的,几乎都是gen_server或者gen_fsm的模型。那么程序运行起来的时候 我们如何查看gen_server的内部状态呢。有2种方法:
1. 自己写个类似于info这样的函数,来获取状态。
2. 利用系统现有的架构。sasl应用带了一个si的东西 全名是status inspector, 这个东西就是设计来帮用户解决这个问题的。

实验开始:

root@nd-desktop:~# cat abc.erl
-module(abc).
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-export([format_status/2]).
-export([test/0]).

-record(state, {a, b}).

-define(SERVER, ?MODULE).

start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

test()->
    gen_server:call(?SERVER, {test, "param1"}).

init([]) ->
    {ok, #state{a=hello, b=world}}.

handle_call({test, _} = Request, _From, State) ->
    io:format("got msg ~p~n", [Request]),
    {reply, ok, State};

handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

format_status(_Opt, [_PDict, #state{a=A,
                                    b = B
                                    }]) ->
   
    [{data, [{"a===", A},
             {"b===", B}]}].
root@nd-desktop:~# erl -boot start_sasl
Erlang R13B03 (erts-5.7.4) [/source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]


=PROGRESS REPORT==== 29-Oct-2009::16:07:24 ===
          supervisor: {local,sasl_safe_sup}
             started: [{pid,<0.35.0>},
                       {name,alarm_handler},
                       {mfa,{alarm_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 29-Oct-2009::16:07:24 ===
          supervisor: {local,sasl_safe_sup}
             started: [{pid,<0.36.0>},
                       {name,overload},
                       {mfa,{overload,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 29-Oct-2009::16:07:24 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.34.0>},
                       {name,sasl_safe_sup},
                       {mfa,
                           {supervisor,start_link,
                               [{local,sasl_safe_sup},sasl,safe]}},
                       {restart_type,permanent},
                       {shutdown,infinity},
                       {child_type,supervisor}]

=PROGRESS REPORT==== 29-Oct-2009::16:07:24 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.37.0>},
                       {name,release_handler},
                       {mfa,{release_handler,start_link,[]}},
                       {restart_type,permanent},
                       {shutdown,2000},
                       {child_type,worker}]

=PROGRESS REPORT==== 29-Oct-2009::16:07:24 ===
         application: sasl
          started_at: nonode@nohost
Eshell V5.7.4  (abort with ^G)
1> si:start(). %必须手动启动

=PROGRESS REPORT==== 29-Oct-2009::16:07:31 ===
          supervisor: {local,sasl_sup}
             started: [{pid,<0.43.0>},
                       {name,si_server},
                       {mfa,{si_sasl_supp,start_link,[[]]}},
                       {restart_type,temporary},
                       {shutdown,brutal_kill},
                       {child_type,worker}]
{ok,<0.43.0>}
2> si:help().

Status Inspection tool - usage
==============================
    For all these functions, Opt is an optional argument
    which can be 'normal' or 'all'; default is 'normal'.
    If 'all', all information will be printed.
    A Pid can be: "<A.B.C>", {A, B, C}, B, a registered_name or an abbrev.
ANY PROCESS
si:pi([Opt,] Pid)   - Formatted information about any process that
                      SI recognises.
si:pi([Opt,] A,B,C) - Same as si:pi({A, B, C}).
si:ppi(Pid)         - Pretty formating of process_info.
                      Works for any process.
MISC
si:abbrevs()        - Lists valid abbreviations.
si:start_log(Filename) - Logging to file.
si:stop_log()
si:start()          - Starts Status Inspection (the si_server).
si:start([{start_log, FileName}])
si:stop()           - Shut down SI.
ok
3> abc:start_link().
{ok,<0.46.0>}
4> abc:test().
got msg {test,"param1"}
ok
5> sys:log(abc,true). %打开gen_server的消息log功能
ok
6> abc:test().  %这个请求消息被记录
got msg {test,"param1"}
ok
7> si:pi(abc). %好戏开始

Status for generic server abc                                                 
===============================================================================
Pid                                                                    <0.46.0>
Status                                                                  running
Parent                                                                 <0.41.0>
Logged events  %这个是log到的消息
         {10,
         [{{out,ok,<0.41.0>,{state,hello,world}},
           abc,
           {gen_server,print_event}},
          {{in,{'$gen_call',{<0.41.0>,#Ref<0.0.0.85>},{test,"param1"}}},
           abc,
           {gen_server,print_event}}]}

%这个是format_status的结果  如果没有format_status那么导出是 {a=hello, b=world}

a===                                                                      hello
b===                                                                      world

ok
8> si:ppi(abc).

Pretty Process Info
-------------------
[{registered_name,abc},
{current_function,{gen_server,loop,6}},
{initial_call,{proc_lib,init_p,5}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[<0.41.0>]},
{dictionary,[{'$ancestors',[<0.41.0>]},{'$initial_call',{abc,init,1}}]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.25.0>},
{total_heap_size,233},
{heap_size,233},
{stack_size,9},
{reductions,117},
{garbage_collection,[{fullsweep_after,65535},{minor_gcs,0}]},
{suspending,[]}]
ok

9> sys:get_status(abc).
{status,<0.46.0>,
        {module,gen_server},
        [[{'$ancestors',[<0.41.0>]},{'$initial_call',{abc,init,1}}],
         running,<0.41.0>,
         [{log,{10,
                [{{out,ok,<0.41.0>,{state,hello,world}},
                  abc,
                  {gen_server,print_event}},
                 {{in,{'$gen_call',{<0.41.0>,#Ref<0.0.0.85>},
                                   {test,"param1"}}},
                  abc,
                  {gen_server,print_event}}]}}],
         [abc,{state,hello,world},abc,infinity]]}

结论:
这个是文档未公开的功能。上面演示了如何sys打开log, 如何察看gen_server的状态

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: , , , ,

Erlang和port通讯的数据格式

October 22nd, 2009 3 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang和port通讯的数据格式

erlang内置的port非常强大,是erlang通往外面世界的通道,所以port和erlang程序的通讯的数据格式影响了通讯的效率,和稳定性。我们在选择格式的时候, 会优先考虑到erlang的特性和port程序编写语言的特点,选出一种2者都容易处理的格式。

通讯通常有2种,基于行的文本和2进制格式。

行通讯最容易,因为是文本,调试起来就很方便。 形如这样的格式:
request args\n erlang编码这种格式就是加个\n, 解码可以用driver的{line, xxx}选项。而外部程序比如说c 解码可以用fgets, 编码也是加个\n. 缺点是: 表达上比较受限 不好表示结构数据。

2进制格式,形如这样的格式:
4个字节包长度 包体 . erlang和解码都可以利用driver的{packet,4} 自动把包体接处理。而外部程序比如说c 处理这样的也非常轻松。

包体有以下几种留下的格式:
1. 自定义格式。 比如: 4个字节cmd + 2个字节字符长度 + 字符
只要erlang和外部程序都能同样这种格式就好。erlang有很强大的binary处理这种事情很轻松, c同样也是。 缺点是太繁琐,格式变化的时候 容易漏掉东西。

2. erlang的外部协议格式。 erlang编码可以用term_to_binary, 解码用binray_to_term. c程序用ei库俩编解码。 这样erlang端的工作量就很小, c端的麻烦些。

3. json这样的格式。 erlang和c都用现成的json库来编码解码。

4. asn.1格式。erlang有强大的内置的asn编码解码。c端也有asn1c这样的编解码器。 写个asn1规格 2边各自生成代码,这样最轻松 而且能表达数据很轻松,推荐使用。

Post Footer automatically generated by wp-posturl plugin for wordpress.

javaeye上我写的erlang的帖子电子书下载

October 15th, 2009 3 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: javaeye上我写的erlang的帖子电子书下载

如题, 方便大家阅读,这个电子书记录了俺的研究过程,希望对大家有帮助。
erlang深度分析文章下载

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: , ,

leex文法分析的效率

October 12th, 2009 No comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: leex文法分析的效率

R13B新添加的leex相当于c的lex, 在做文法分析非常方便,但是效率如何呢? leex的example里面带了个erlang_scan和erlang标准的发布版的erl_scan兼容,所以我们来对比测试下效率。

注意用R13B03,因为R13B02的erlc漏掉了编译xrl格式。

以下是实验:

root@nd-desktop:~# git clone git://github.com/rvirding/leex.git
root@nd-desktop:~# cd leex/examples/
root@nd-desktop:~/leex/examples# cat test_scan.erl
-module(test_scan).
-export([start/1]).
start([A])->
    {ok, F} = file:open(atom_to_list(?MODULE)++".erl", [read]),
    {ok, S} = file:read(F, 9999999),
    file:close(F),
    N = list_to_integer(A),
    test(N, fun erlang_scan:string/1, S, "erlang_scan"),
    test(N, fun erl_scan:string/1, S, "erl_scan"),
    ok.

test(N, F, S, Ts)->
    Start = erlang:now(),    
    dotimes(N, fun (_) ->
                       F(S)
               end),
    io:format("~s run ~w ms~n", [Ts,round(timer:now_diff(now(), Start) /1000)]).

dotimes(0, _) -> done;
dotimes(N, F) ->
    F(N),
    dotimes(N - 1, F).
root@nd-desktop:~/leex/examples# erlc erlang_scan.xrl
root@nd-desktop:~/leex/examples# ls *.erl
erlang_scan.erl  test_scan.erl
root@nd-desktop:~/leex/examples# erlc *.erl
root@nd-desktop:~/leex/examples# erl -noshell -run test_scan start 10000 -s erlang halt
erlang_scan run 2208 ms
erl_scan run 1181 ms

%% 这个版本稍微慢点

root@nd-desktop:~/leex/examples# erlc +native *.erl
root@nd-desktop:~/leex/examples# erl -noshell -run test_scan start 10000 -s erlang halt
erlang_scan run 1292 ms
erl_scan run 1238 ms

结论是: leex产生的代码和手写的效率几乎差不多。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: ,

【CN-Erlounge-IV】会议议程安排

October 12th, 2009 2 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 【CN-Erlounge-IV】会议议程安排

以下是会议议程安排。更多信息访问: http://ecug.org/
2009-11-6

* 讲师入住酒店
* 会务人员&讲师小聚

2009-11-7

08:30 ~ 09:00 签到
09:00 ~ 09:15 开场
09:15 ~ 10:15 成立涛 – Erlang开发实践
10:15 ~ 10:30 提问&交流
10:30 ~ 11:30 余锋 – Erlang系统调优
11:30 ~ 11:45 提问&交流
11:45 ~ 12:00 集体拍照留念

12:00 ~ 13:00 午餐
13:00 ~ 13:30 休息

13:30 ~ 14:30 范赟、周琦 – 恶狼战役及社区养成
14:30 ~ 14:45 提问&交流
14:45 ~ 15:45 Stewart Mackenzie – An Erlang Implementation of Restms
15:45 ~ 16:00 提问&交流
16:00 ~ 16:15 茶歇(水果)
16:15 ~ 17:15 金尹 – CUDA Programming,一次异域之旅
17:15 ~ 17:30 提问&交流

17:30 ~ 18:30 晚餐
18:30 ~ 19:00 休息
19:00 ~ 20:00 李杰、崔博 – ac_actor: Erlang进程模型在C++中的实践
20:00 ~ 21:00 许式伟 – CERL: 谈谈“Boost.ASIO、Erlang与服务器编程”

21:00 全天会议结束

2009-11-8

08:30 ~ 09:30 方焜平 – 利用已有单机程序组建分布式模型的分析与实例
09:30 ~ 09:45 提问&交流
09:45 ~ 10:45 侯明园 – 基于Erlang实现的MMO服务器连接管理服务
10:45 ~ 11:00 提问&交流(上水果)
11:00 ~ 12:00 沙龙。开放式讨论(社区建设、技术走向等等)。

12:00 ~ 13:00 午餐
13:00 ~ 13:30 休息

13:30 ~ 14:30 周爱民 – 谈谈erlang网络环境下的几种数据流转形式
14:30 ~ 14:45 提问&交流
14:45 ~ 15:45 吴峥涛 – XEngine介绍
15:45 ~ 16:00 提问&交流

16:00 会议结束

Post Footer automatically generated by wp-posturl plugin for wordpress.

erlang动态解释

October 12th, 2009 No comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: erlang动态解释

erlang的代码运行有2种方式 1. 编译成opcode 2. eval. 这2种形式都需要把erl代码翻译成abstract code, 然后在不同的途径分别开.

通常情况下我们在eshell 里面输入的东西都是动态eval的. erl还支持命令行动态解释. erl -eval

看下init.erl

start_it({eval,Bin}) ->
    Str = binary_to_list(Bin),
    {ok,Ts,_} = erl_scan:string(Str),
    Ts1 = case reverse(Ts) of
              [{dot,_}|_] -> Ts;
              TsR -> reverse([{dot,1} | TsR])
          end,
    {ok,Expr} = erl_parse:parse_exprs(Ts1),
    erl_eval:exprs(Expr, []),
    ok;

我们看到express先文法扫描, 确认以dot结尾, 然后进行语法分析,形成abstract code, 最后 erl_eval解释abstact code.
我们注意到 在erl_parse的时候 表达式是这样的 f()->expr. 这就解释了为什么在shell里面无法定义函数,无法定义module什么的.

io模块和shell模块都是以上面的形式来动态eval的. 这个特性很好用, 配合parse_transform, 我们可以很容易自己实现个DSL语言.

Post Footer automatically generated by wp-posturl plugin for wordpress.