[连载]《C#通讯(串口和网络)框架的计划与落实》-4.设备驱动管理器的筹划

作者介绍:jsOAC。迪拜学童,伪专业徒步爱好者,伪军品爱好者

目       录

本身是一个不要紧就爱徒( Liu )步( Wan
)的新加坡男孩儿,自从几年前高考截至后接触到了露天徒步——这一个给自身备感“高大上”的户外项目后,就一发不可收拾。那么在步行当中呢,我认为最不可以不够的东西就是背包。好的背包除了令人奋发饱满,更首要的是它可以带领过多事物、解放双手、保持身体平衡,使得行程更为安全舒心。

第四章           设备驱动管理器的设计… 2

那么对于背包的选择,我总结为三点——背包大小、舒适性和耐用性。

4.1           接口定义… 2

一、关于背包大小

4.2           设备容器… 7

背包大小,即背兼容量,一般以多少公升表示。重要以 50L 为界,50L 以下 25L
以上为中短途用背包,50L
以上为远途用背包。对于背包大小的抉择,这方面尚未硬性的确定,首要仍旧取决于与您自己的步行所需物品的有些,够装下您要带的物料就行。所以不同品种,不同距离的步行所需要的背包大小是不雷同的。一般的话,长距离步行(
10天以上)需要一个 70L 左右的背包,中距离徒步( 3 – 10 天)需要 45L
左右的背包,短距离徒步( 1-3 天)需要 30L
左右。可是这并不代表你需要买那么多背包,假若不平常徒步,一个 45L
左右的背包就可以知足。

4.3           生成设备ID.. 7

二、舒适性

4.4           对配备容器操作的互斥… 8

舒适性,顾名思义,就是指在徒步过程中背包的和颜悦色程度。对于自身要好的话,这是最要紧的参数了。相信自己,你可不会想没走几公里,就意识肩膀,脖子酸痛,然后心里的绝无仅有念头就是回家…那么怎么拔取一个让您会倍感舒适的背包呢?那就是看背负系统!所谓背负系统,通俗一点说,就是将原来应该接受在肩膀上的一有些重量,转移到你的腰上。以减轻身体的承负。并且,背负系统仍是可以够依照不同身材,不同身高举行调试,以高达最佳的动静。所以在我们挑选背包时,一定要留心其承受系统的型号(一般分为
S 、M 、L 、XL 这四种),不要过大,不要过小。

4.5           拿到装备列表… 8

图片 1

4.6           设备计数器的独特用处… 8

本来,有些人会说您怎么只谈背负,透气性难道不是舒适的第一标准之一吧?我很同意,但是就自我要好在大太阳下走数个刻钟的经历看,这点点透气性并没有怎么帮(
luan )助( yong )。

4.7           小结… 10

三、关于耐用性

 

露天背包,尤其是这种大容量的背包,价格不菲,你一定不想没用两遍,背包就坏了。所以当我们在增选时,耐用性也是一项分外着重的要素(土豪就径直忽略这条吧)。

第四章     设备驱动管理器的计划

   
设备驱动管理器是对IRunDevice设备驱动接口的治本,是框架紧要的组成部分之一。不管设备驱动管理器怎么统筹、以什么样花样存在,在概念上必然是存在的。设计好的装置驱动管理器对于框架平台的安居乐业运行重大。

  
在介绍装备驱动管理器以前,先简单介绍一下IO控制器(IIOController),它紧要负责对IO和设备开展调度,并驱动装置运行,在《第5章
串口和网络的IO设计》举办详尽的牵线。也就是说一个IO控制器可能会对应两个设备驱动(插件)。

  
早期的时候,每个IO控制器都有一个设施驱动管理器。在框架平台启动的时候,按照设备驱动的报道参数把相应的配备驱动分配到对应的IO管理器;当IO参数暴发变化的时候,会接触事件,把该装备驱动从此时此刻IO控制器移动到另一个IO控制器。

  
从作业角度来考虑,这样做并没有怎么问题,并且平素运行的很平静。不过,从模块化、扩张性角度来设想,不是太美好,如若在任哪个地点方调用某一个设施驱动时,无法直接、很快的找到该设施驱动,必要遍历IO控制器再配合相应的配备驱动,并且操作麻烦以及功用不高。

  
在对框架平台开展重构的时候,把该问题举行了重新考虑,并把相关联的题材一并化解。把每个IO控制器中的设备驱动管理器举行了整合,用一个设备驱动管理器来完成框架平台的调和工作。

  
这块涉及到的技能并不难,也很容易通晓,不过在筹划过程中需要专注一些细节问题,这么些题目可能影响框架平台的平稳。

这就是说怎么看一个背包耐不牢靠呢?很简单,买一个拿回家用用看呗…(好呢,我是逗X)。其实在置办往日,大家紧要看两点,一是料子,二是做工(也就是结不结实)。面料呢,一般是都是以尼龙为主,按照面料的强度一般分为250D、
500D 与1000D
。而相较于面料做工就更简短了,重要就是要看背带与包体等连接处的结果程度,那与大家平日购买通勤包一样,就不再啰嗦了。下边我要介绍的背包我会用天数来做推荐的。

4.1    接口定义

    先定义一个接口(IDeviceManager<TKey,
电视alue>),确定设备驱动管理器都要成功什么效劳,扩大设备、删除设备、拿到装备和列表、以及其余的效果。接口代码如下:

public interface IDeviceManager<TKey, TValue> : IEnumerable<TValue> where TValue : IRunDevice
{
       /// <summary>
       /// 新建设备的ID,且唯一
       /// </summary>
       /// <returns></returns>
       string BuildDeviceID();

       /// <summary>
       /// 增加设备
       /// </summary>
       /// <param name="key"></param>
       /// <param name="val"></param>
       void AddDevice(TKey key, TValue val);

       /// <summary>
       /// 删除设备
       /// </summary>
       /// <param name="key"></param>
       void RemoveDevice(TKey key);

       /// <summary>
       /// 移除所有设备
       /// </summary>
       void RemoveAllDevice();

       /// <summary>
       /// 获得值集合
       /// </summary>
       /// <returns></returns>
       List<TValue> GetValues();

       /// <summary>
       /// 获得关键字集合
       /// </summary>
       /// <returns></returns>
       List<TKey> GetKeys();

       /// <summary>
       /// 获得设备的ID和名称
       /// </summary>
       /// <returns></returns>
       Dictionary<int, string> GetDeviceIDAndName();

       /// <summary>
       /// 获得高优先运行设备
       /// </summary>
       /// <param name="vals"></param>
       /// <returns></returns>
       TValue GetPriorityDevice(TValue[] vals);

       /// <summary>
       /// 获得单个设备
       /// </summary>
       /// <param name="key"></param>
       /// <returns></returns>
       TValue GetDevice(TKey key);

       /// <summary>
       /// 获得设备数组
       /// </summary>
       /// <param name="para">IP或串口号</param>
       /// <param name="ioType">通讯类型</param>
       /// <returns></returns>
       TValue[] GetDevices(string para, CommunicationType ioType);

       /// <summary>
       /// 获得指定IP和工作模式的网络设备
       /// </summary>
       /// <param name="remoteIP"></param>
       /// <param name="workMode"></param>
       /// <returns></returns>
       TValue[] GetDevices(string remoteIP, WorkMode workMode);

       /// <summary>
       /// 获得指定工作模式的网络设备
       /// </summary>
       /// <param name="workMode"></param>
       /// <returns></returns>
       TValue[] GetDevices(WorkMode workMode);

       /// <summary>
       /// 获得设备数组
       /// </summary>
       /// <param name="ioType"></param>
       /// <returns></returns>
       TValue[] GetDevices(CommunicationType ioType);

       /// <summary>
       /// 按设备类型获得设备
       /// </summary>
       /// <param name="devType"></param>
       /// <returns></returns>
       TValue[] GetDevices(Device.DeviceType devType);

       /// <summary>
       /// 判断设备是否存在
       /// </summary>
       /// <param name="key"></param>
       /// <returns></returns>
       bool ContainDevice(TKey key);

       /// <summary>
       /// 根据输入参数,判断是否包括设备
       /// </summary>
       /// <param name="para">IP或串口号</param>
       /// <param name="ioType">设备通讯类型</param>
       /// <returns></returns>
       bool ContainDevice(string para, CommunicationType ioType);

       /// <summary>
       /// 设置用户级别
       /// </summary>
       /// <param name="userlevel"></param>
       void SetUserLevel(UserLevel userlevel);

       /// <summary>
      /// 设置是否注册
       /// </summary>
       /// <param name="isreg"></param>
       void SetIsRegLicense(bool isreg);

       /// <summary>
       /// 获得可用设备数
       /// </summary>
       int Count { get; }

       /// <summary>
       /// 获得设备的计数器的值
       /// </summary>
       /// <param name="key"></param>
       ///<returns></returns>
       int GetCounter(TKey key);

       /// <summary>
       /// 设置计数器的值
       /// </summary>
       /// <param name="key"></param>
       /// <param name="val"></param>
       void SetCounter(TKey key, int val);
}

 4.2    设备容器

  
设备驱动管理器是对Dictionary<Key,Value>的包装,Key是设备驱动的ID,Value是IRunDevice设备驱动接口。设备驱动管理器需要跨线程应用,所以对Dictionary操作要加线程同步锁。

   当时应用的是.NET Framework 2.0框架,没有ConcurrentDictionary(Of TKey,
电视alue)字典类,那个类的拥有国有和受保障的分子都是线程安全的,使用原子性操作,适合三个线程之间同时选取。再重构时可以采取ConcurrentDictionary类代替Dictionary类,因为ConcurrentDictionary的享有操作使用到了Monitor线程同步类,不需要自己再开展打包。

   不贴ConcurrentDictionary类的源代码了,具体应用参考MSDN。

图片 2

4.3    生成设备ID

    查寻设备驱动管理器中最大的设备ID,并在此基础上加1。这块代码很粗略,

如下:

public string BuildDeviceID()
{
       if(_dic.Count>0)
       {
          int maxID=_dic.Max(d => d.Value.DeviceParameter.DeviceID);
          return (++maxID);
       }
       else
       {
              return 0;
       }
}

   
扩大设备驱动是内需扭转设备ID,一般拔取手动扩展设备驱动,所以在这块不需要加线程同步锁。

中远距离徒步:1~3天

4.4    对设施容器操作的排挤

框架平台具有组件要共享设备驱动管理器,所以会涉嫌到跨线程应用,特别

是当集合暴发转移的时候,可能会出现非凡。例如:启动框架平台的时候,IO控制器已经起步,IO控制器从设备驱动管理器提取自己的装置列表,可是此时有可能还不曾加载完设备驱动,当有新的配备驱动扩展到设备驱动管理时,可能会吸引争辨。

   
所以,在扩展设备、删除设备和拿到装备列表的时候扩大了线程同步锁,例如:lock
(_SyncLock)。

arc’teryx  始祖鸟 ——Kata 45

4.5    拿到装备列表

有三个得到装备的构造函数(GetDevices),重假使满意不同的行使场景。

请参考“4.1接口定义”。

   
此外,得到高优先运行设备的GetPriorityDevice函数在上一章节早已介绍了。

图片 3

4.6    设备计数器的与众不同用途

    在接口定义中有SetCounter和GetCounter六个函数,用在通讯过程中。

   
应用场景是这样的,在出现和约束通讯模式中,设备驱动从来处在在简报正常的景色下,不过忽然发生线路中断或其他原因促成无法接受到数码时,那么设备驱动从来不可能吸纳到数量,也无从对报道状态举办检测以及变更相应的数额信息,也就是说现实情况已经发出变更,但是设备驱动却一筹莫展拿到响应。

   
为了以防这种情景的产出,设备驱动每便发送数据时,通过GetCounter函数得到当前配备驱动的计数器,对计数器(变量)+1操作,并因此SetCounter函数把计数器(变量)再写到设备驱动管理器中。在特别接收数据的时候,执行同一的流程,可是举办-1操作。假设从来发送数据,而并未收受到数码时,当前设施驱动的计数器就会一向在添加。假使超过等于某个值的时候,就会经过RunIODevice(new
byte[]{})驱动当前配备,执行总体设施处理流程,二次开发的代码块就会被调用,来成功此类应用场景的图景改变和数据变化。代码如下:

int counter = DeviceManager.GetInstance().GetCounter(dev.DeviceParameter.DeviceID.ToString());
int sendNum = SessionSocketManager.GetInstance().Send(dev.DeviceParameter.NET.RemoteIP, data);
if (sendNum == data.Length && sendNum != 0)
{
       DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, "发送请求数据");
       Interlocked.Increment(ref counter);
}
else
{
       Interlocked.Increment(ref counter);
       DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, "尝试发送数据失败");
}
dev.ShowMonitorIOData(data, "发送");
if (counter >= 3)
{
       try
       {
              dev.RunIODevice(new byte[] { });
       }
       catch (Exception ex)
       {
              DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, ex.Message);
              GeneralLog.WriteLog(ex);
       }
       Interlocked.Exchange(ref counter, 0);
}
DeviceManager.GetInstance().SetCounter(dev.DeviceParameter.DeviceID.ToString(), counter);

  
对于发送和接收数据会在不同的线程上落成,在对计数器(变量)举办+1和-1操作的时候使用到了Interlocked类,用于五个线程共享的变量提供原子操作,避免在多处理器上并行操作时或许引发的老大或数量遭到破坏。

Arc’teryx 国君鸟 Kea Kata 45
顶级户外背包

4.7    小结

  
这样改造后,不仅可以在IO控制器对设施开展引用,也能够在其他零件使用。假设曰镪类似的情事,希望采用ConcurrentDictionary类。

 

笔者:唯笑志在

Email:504547114@qq.com

QQ:504547114

.NET开发技术联盟:54256083

文档下载:http://pan.baidu.com/s/1pJ7lZWf

合法网址:http://www.bmpj.net

图片 4

皇上鸟作为户外运动的五星级品牌,这款kata 45
是二零一二年主公鸟推出的产品,经过新规划,背包面料坚固耐用,包体采取 420D
Cordura HT 面料,底部选用 840D 面料,耐磨防刮;T6061 铝材支撑 EV50
泡沫作为承担,非凡贴合,尽管长日子背上徒步,也照样舒适。45L 容量的
kata是主公鸟 2 日徒步行程主推款式,对 altra 系列轻量
缩短后推出的制品。相相比 axios 系列面料要结实耐操。

Gregory ——Z35背包 L款

格雷戈里 格里高利 Z35 L
轻装登山包徒步包

图片 5

图片 6

这款背包是 格雷戈里(格里高利)品牌推出的一款户外背包,L款的容量为 38L
,怎么说呢,这款背包整体表现很平均,不管是从外观上,设计上,背负系统上都尚未怎么非凡的地点。可是自己为此把它座落这里,是因为它的性价比极高,价格相较于我下边推荐的arc’teryx,价格便宜了无数,能够说,这是一款适用于新手入门的一款背包。

Mystery Ranch 3D Assult pack

Mystery Ranch 神秘农场 3 Day Assault Pack
三日抨击背包

图片 7

Mystery Ranch 3D
背包,这是本身眼前在行使的背包之一,也以为是最好的短途背包,那儿可没有之一!关于神秘农场的牵线呢?我在这边就不多说了,毕竟是小众中的小众,有亟待的同室请自行百度呢,总计就是三个词:顶尖,昂贵!这款背包的效应就像其名字一样,3日短途攻击背包,33L
的容量以及美好的挂载能力,可以知足你这 3
天内所需的装有装备。最着重的就是其负责系统可以说是完美,满载状态下背上那多少个包,你的肩头也不会感受到过多的下压力,可以让你在徒步过程中感受到其相应的野趣。

中距离徒步 :3~10天

Arc’teryx Altra 75L

Arc’teryx 天皇鸟 75 LT Pack
户外背包

图片 8

这款背包拥有75L的重特大容量,C2的承受系统与轻巧耐用的经典面料,让这款背包一下子抓人眼球。贴合腰带既宽大又紧绷,由回忆海绵构成,提供全天的舒畅与巩固,能防范大负荷造成的下挫。增添一个腰部枢轴,加强机动性和平安,它能让腰带在行动、登高、越野时跟随髋部旋转,缩短摩擦。这款背包不仅经受住了户外严刻的考验,并且也因其风尚的外观,也让其取得了《
Backpacker 》杂志发表的特等编辑选用奖。

Mystery Ranch ——SATL攻击背包

Mystery Ranch 神秘农场 SATL Assault Ruck
高端攻击包

图片 9

那款背包也是 Mystery Ranch 的一款经典,就当前的话,神秘农场 Mystery
Ranch ( dana design)  军版 SATL 战术包是海豹
DEVGR、陆战队等专门单位最新配发的特大型背包。

图片 10

它具有 60 升容量,超轻的分量,该款背包采取轻量高强度 CORDURA 500D 尼龙和
Mystery Ranch 的
YOKE背负系统,采纳异常规的承担设计,是背负者感到丰盛的舒适性,适用于远途行动。可是这款背包,在其外观上,充满了“男人”的味道,不太适用于在都市间穿行,倘使您背着这款背包走在大街上,你会取得
100% 的回头率!

Kifaru—— Navigator G2 犀牛战术背包

Kifaru Navigator G2 65.5
升犀牛战术背包

图片 11

这也是一款不逊于 SATL 的一款背包,关于 Kifaru
的介绍,在此间自己也不多说了。这款包有 65L 的容量,1000D
的一级面料,优良的担当系统。这款背包的经典之处在于,整个背包都蕴含魔术带,可以圆满的开展挂载,以满意某些特殊情形下特种的户外装备。并且,这款背包在大负重下,也得以更好的与身体贴合!将重量均匀的分配的顺序点!

长距离步行:10天以上

Mystery Ranch —— 6500 Backpack

Mystery Ranch 神秘农场 6500
背包

图片 12

本身实际远非打算写 10 天以上这样的远途用背包的,因为 10
天以上的步行线路国内很少,并且相较于中短途来说,路线都很偏僻。这样的步行线路更像是冒险性质的,所以它的危险性相对来说很高,不提议新手去举办这样的步行运动。可是,不写的话好像又少了有些什么,所以自己就推荐
Mystery Ranch NICE 6500 Backpack 这一款啊。

图片 13

这又是一款 Mystery Ranch
的背包,它的定势是捕猎或登山用包。这是一款全方位充斥情况下可高达 107L
的怪兽。像这么大容量的包,一般都是狩猎用,因为要在一片区域内驻扎很久,所以生活必备品也需要广大。也不言而喻,它的危险性是很高的,是内需肯定的身体素质,技巧知识与勇气的。

这款背包拔取的要么NICE背负,完全可以忍受住在充满状态下的轻重,并能够让您感觉到轻松舒适。和地点介绍的SATL拔取的面料也如出一辙,500D尼龙,充分结实牢固有能尽量的减轻背包的正经。这款包从各样方面来说早已高达了最好,可是价格稍微略贵。但自我个人觉得这依旧是最好的远途户外背包。

以上这几款背包都是自个儿在这几年中亲身使用过的背包中觉得最佳的,可是其个人主观因素也正如多。不管怎么说,希望各位在阅读之后可以对窗外背包有一定的垂询。并得以去尝尝徒步,尝试户外运动,享受它带动的乐趣!