从5900到65535之间随机分配一个数字——erlang实现
来源:互联网 发布:java 英文日期转换 编辑:程序博客网 时间:2024/06/12 23:14
vnc是一款开源的远程控制软件,它能完整的将窗口界面,通过网络传输到另外一台计算机的屏幕上。在linux下,vnc包括四个命令:vncserver,vncviewer,vncpasswd,vncconnect。在连接一台计算机的时候,需要知道对方计算机的IP和端口号,在我们的项目中,虚拟机的端口号是由master分配的,因此,master就要实现vncport的分配了,vncport的分配范围一般在5900到65535之间。
之前写的vncport的分配是用mnesia数据库来进行的,分配一个port之后在数据库中进行标记,也没有涉及比较复杂的算法,这种方法可以实现所要求的功能,但是在这将近65536个数据当中,每次要找一个没有使用的数据,这个时间也是比较长的。
后来,在学习进程的pid号分配的时候,也涉及到了这个问题,不过进程的pid分配范围是在0到32767之间,上面的数目是这个数目的2倍。因此,想借用内核中的pid分配算法(pid位图)来实现这里的vncport分配问题。
先来看一下pid位图算法:
为了表示32768个进程号是不是分配出去没有,我们要占用32768/8=4096个字节来标识,用每一位来标记一个pid号是不是分配出去。为此,我们可以定义一个这样的结构体:
typedef struct pidmap
{
unsigned int nr_free;
char page[4096];
} pidmap_t;
用nr_free表示未分配出去的pid号的数目。
如果要根据一个给定pid号,要找它在这个结构体当中所对应的位的时候,可能我们首先想到的是下面的这个算法:
我们把上面的存放位图的变量想像成一个4096行,8列的表。首先给pid除以8,然后取整,即int a=(pid/8),将得到的a的值作为pidmap.page的下标,也就是pidmap.page[a],然后用int b=(pid%8)得到对应位的0—7之间的编号,这样的话,就唯一确定了一个pid编号在pidmap.page中的具体位置。
这个方法也是可以实现的,但是内核当中是通过移位操作来实现的。我们可以抽象出一张表,这个表有32列,1024行,这个刚好是一个页的大小。这个时候,我们可以通过pid的后5位值(变化范围在0—31之间)来确定在某一行的具体的列。通过pid的高27位(pid本身是32位的)来表示在具体的某一行。所以我们可以通过移位操作来实现。
具体的移位操作主要有两句:
unsigned long mask = 1UL << (offset & 31);
unsigned long *p = ((unsigned long*)addr) + (offset >> 5);
其中的offset表示的是一个要处理的pid号。
这样就可以实现了。
有关的详细的解释以及应用可以看我的博客:
http://blog.chinaunix.net/space.php?uid=22566367&do=blog&id=2845765
下面开始erlang中的vncport的分配。
Erlang 是面向函数式编程的,进程本身没有全局变量,在函数上下文中,可有局部变量,所有的局部变量都是readonly,并只能被赋值一次。因此,为了保存这个位图,可以借助数据库进行保存。
-record(vncport, {vnc_id, vnc_value}).
数据库弄两列,一列是vnc_id,一列是vnc_value。在这个数据库的每一项中,vnc_id表示的是vncport的一个地址,具体对应的是某一个vncport的高11位(65535是16位);而vnc_value是一个32位的数据,用来表示32个vncport。
具体程序代码是:
- %% File: vncport.erl
- %% Created: 2011-10-18
- %% Description:
- -module(vncport).
- -date("2011.10.18").
- %%
- %% Include files
- %%
- -include_lib("stdlib/include/qlc.hrl").
- %%
- %% Export functions
- %%
- -export([start/0, stop/0, set_bit/1, get_next_vncport/0, free_vncport/1]).
- -record(vncport, {vnc_id, vnc_value}).
- %%
- %% API functions
- %%
- start() ->
- mnesia:stop(),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- mnesia:start(),
- mnesia:create_table(vncport, [{attributes, record_info(fields, vncport)}]),
- vncport_init(),
- % mnesia:dirty_update_counter(vncport, last_used, -1),
- F = fun() ->
- Row = #vncport{vnc_id=last_used, vnc_value=-1},
- mnesia:write(Row)
- end,
- mnesia:transaction(F),
- io:format("mnesia start~n"),
- alloc_vnc(0, 5900).
- stop() ->
- mnesia:stop().
- get_next_vncport() ->
- %% find last used vncport
- F = fun() ->
- Query = qlc:q([X#vncport.vnc_value || X <- mnesia:table(vncport), X#vncport.vnc_id =:= last_used]),
- [E] = qlc:e(Query),
- io:format("Last used vncport is:~p~n", [E]),
- E
- end,
- {atomic, R} = mnesia:transaction(F),
- Result = R+1,
- io:format("init vncport value is ~p~n", [Result]), %% debug info
- search(search, Result).
- free_vncport(N) ->
- Mask = 1 bsl (N band 31),
- Address = N bsr 5,
- io:format("Mask:~p, Address:~p~n", [Mask, Address]), %% debuf info
- F = fun() ->
- Query = qlc:q([X#vncport.vnc_value || X <- mnesia:table(vncport), X#vncport.vnc_id =:= Address]),
- [E] = qlc:e(Query),
- Value = E band (bnot Mask),
- New = #vncport{vnc_id=Address, vnc_value=Value},
- mnesia:write(New)
- end,
- mnesia:transaction(F).
- set_bit(N) ->
- Mask = 1 bsl (N band 31),
- Address = N bsr 5,
- io:format("set number:~p~n", [N]), %% debuf info
- % io:format("Mask:~p, Address:~p~n", [Mask, Address]), %% debuf info
- F = fun() ->
- Query = qlc:q([X#vncport.vnc_value || X <- mnesia:table(vncport), X#vncport.vnc_id =:= Address]),
- [E] = qlc:e(Query),
- Value = E bor Mask,
- New = #vncport{vnc_id=Address, vnc_value=Value},
- mnesia:write(New),
- io:format("update over :~p ~p~n~n", [Value, New]) %% debug info
- end,
- mnesia:transaction(F).
- %%
- %% Local Functions
- %%
- vncport_init() ->
- F = fun(N) ->
- init_one_vncport(N)
- end,
- for(0, 2047, F).
- init_one_vncport(N) ->
- Row = #vncport{vnc_id=N, vnc_value=0},
- F = fun() ->
- mnesia:write(Row)
- end,
- mnesia:transaction(F).
- search(over, N) ->
- io:format("vncport ~p can use~n", [N]),
- ok;
- search(search, 65536) ->
- io:format("search ~n"),
- search(search, 0);
- search(search, Vncport) ->
- io:format("search ~p~n", [Vncport]),
- case is_empty(Vncport) of
- true ->
- set_bit(Vncport),
- update_dirty(Vncport),
- search(over, Vncport);
- false ->
- Next = Vncport+1,
- search(search, Next)
- end.
- is_empty(Vncport) ->
- io:format("begin check~n"),
- Mask = 1 bsl (Vncport band 31),
- Address = Vncport bsr 5,
- F = fun() ->
- Query = qlc:q([X#vncport.vnc_value || X <- mnesia:table(vncport), X#vncport.vnc_id =:= Address]),
- [E] = qlc:e(Query),
- Result = E band Mask,
- if
- Result =:= 0 ->
- true;
- true ->
- false
- end
- end,
- {atomic, R} = mnesia:transaction(F),
- io:format("over check, result is ~p~n", [R]),
- R.
- update_dirty(Vncport) ->
- Row = #vncport{vnc_id=last_used, vnc_value=Vncport},
- F = fun() ->
- mnesia:write(Row)
- end,
- mnesia:transaction(F).
- for(Max, Max, F) ->
- [F(Max)];
- for(Min, Max, F) ->
- [F(Min)|for(Min+1, Max, F)].
- alloc_vnc(Min, Min) ->
- io:format("alloc last vnc:~p~n", [Min]),
- set_bit(Min);
- alloc_vnc(Min, Max) ->
- io:format("alloc vnc:~p~n", [Min]),
- set_bit(Min),
- alloc_vnc(Min+1, Max).
API接口说明:
start():初始化数据库。
stop():关闭数据库。
set_bit(N):将N这个vncport端口号置为不可用。
get_next_vncport():得到一个可以分配的vncport端口号。
free_vncport(N):释放vncport为N的这个端口号。
0
上一篇:erlang源程序文件的注释
下一篇:erlang gen_fsm编程框架
相关热门文章
- python 自动化测试平台 Robot ...
- python 自动化测试平台 Robot ...
- python snmp 自动化2-在python...
- 自动化测试详细测试计划 模板...
- python snmp 自动化3-修改pyth...
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- 从5900到65535之间随机分配一个数字——erlang实现
- 使用gen_fsm分配一个5900到65535之间不重复的数字
- erlang获取一个5900——65535之间不重复的一个数据
- 用js实现随机选取10–100之间的10个数字,存入一个数组,并排序
- 用 js 实现随机选取 10–100 之间的 10 个数字,存入一个数组,并排序
- 罗马到数字转换 erlang
- 黑马程序员——从键盘接受一个数字,打印该数字表示的时间,最大单位到天
- 黑马程序员——从键盘接受一个数字,打印该数字表示的时间,最大单位到天
- Spark 机器学习 —— 从决策树到随机森林
- [深度学习] (3)- Keras实现一个简单的翻译器( 从数字到对应的英文 )
- 获取一个从min到max的随机整数
- css3实现随机数字
- 【C语言】——EVC++下srand函数用法(用于随机分配一个数)
- 从随机数生成到随机采样的C++实现
- google笔试题:写出这样一个函数 ,输入一个 n, 输出从1到这个数字之间的出现的1的个数
- PHP把一个指定的数,随机的分配到指定书目的数组中
- 实现--从文件中随机提取一个字符串
- perl实现从一个文件中随机抽取n行
- 关于4G直播的运用,手机app直接控制编码器物联方式简化编码器的操作
- 怎么用CDR X8做出胶片效果
- 云计算项目中遇到erlang的几个小问题
- C++ MFC string转Cstring详解
- erlang源程序文件的注释
- 从5900到65535之间随机分配一个数字——erlang实现
- C++ 无条件转移控制
- erlang gen_fsm编程框架
- 关于angular-cli build后文件路径错误
- 毕业三年,同学基本都辞职了,大部分人看完很有同感~
- 使用gen_fsm分配一个5900到65535之间不重复的数字
- linux释放内存缓冲
- Windows下Caffe框架的测试笔记
- android 调用自带的图库查看图片
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
微商什么好卖
做微商可靠吗
护肤品微商
成人商超
微商内衣
微商网站
微商代理做什么好
怎样注册微商
微商有哪些
微商公司
如何发展微商
微商营销软件
做微商如何加人
微商客
如何注册微商
微商销售模式
微商啥意思
微商发展
韩束微商总代
微商前景怎么样
怎样干微商
微商论坛
微商客服电话
要怎么做微商
微商快速加人方法
思迅商云8
如何找微商
微商怎么玩
微商推广技巧
微商市场
微商服装货源
什么微商好做
微商服务平台
如何做个微商
怎么弄微商
微商是啥
苏宁云商千股千评
微商代理小饰品
商混搅拌车
怎么加微商
怎么做微商啊