OS_MBOX邮箱源码注释
- 格式:doc
- 大小:107.50 KB
- 文档页数:13
SuperSocket源码解析之配置系统⼀继承Net配置系统Net应⽤程序配置机制跟程序集引⽤⼤致类似,均具有继承性,如iis⼏乎每个应⽤程序都会有⼀个Web.config,⽐如我们使⽤vs2012以上版本创建⼀个web应⽤程序会⾃带⼀个web.config配置⽂件,这个配置⽂件属于整个应⽤程序全局配置⽂件,再有某些个别⽬录下也会存在web.config这样的配置⽂件,连名字都跟应⽤程序配置⽂件相同,那么他们看起来重复出现,到底是为何?Net的配置具有继承性,怎么理解?⽐如当前⽂件夹所拥有的配置则作⽤范围仅为当前⽂件夹,如果没有那么他们直接寻找应⽤程序根⽬录下config⽂件并当作⾃⼰的配置⽂件直到应⽤程序根⽬录,其查找顺序由下往上,由近及远,与dll引⽤⼀样本地找不到就去GAC找直到找不到;其中IIS中各个Web.Config继承性就⾮常的典型,所以这⾥也不再举例SuperSocket使⽤了Net配置系统,⽽不是我们平常的⼀个对象序列化成⼀个xml⽂件的私有配置,对⽐起来减少了配置⽂件读写次数,且net配置系统本就如此强⼤⼆ SuperSocket私有配置扩展2.1 TypeProviderSuperSocket对net配置元素进⾏⼀次继承,其代码如下1public class TypeProvider : ConfigurationElement, ITypeProvider2 {3///<summary>4/// Gets the name.5///</summary>6 [ConfigurationProperty("name", IsRequired = true)]7public string Name8 {9get { return this["name"] as string; }10 }1112///<summary>13/// Gets the type.14///</summary>15 [ConfigurationProperty("type", IsRequired = true)]16public string Type17 {18get { return this["type"] as string; }19 }20 }View Code扩展了Name和Type两个属性,这与SuperSocket类型提供⼯⼚类完全对应;1///<summary>2/// Provider factory infomation3///</summary>4 [Serializable]5public class ProviderFactoryInfo6 {7///<summary>8/// Gets the key.9///</summary>10public ProviderKey Key { get; set; }1112///<summary>13/// Gets or sets the name.14///</summary>15///<value>16/// The name.17///</value>18public string Name { get; set; }192021///<summary>22/// Gets or sets the export factory.23///</summary>24///<value>25/// The export factory.26///</value>27public ExportFactory ExportFactory { get; set; }2829///<summary>30/// Initializes a new instance of the <see cref="ProviderFactoryInfo"/> class.31///</summary>32public ProviderFactoryInfo()33 {3435 }3637///<summary>38/// Initializes a new instance of the <see cref="ProviderFactoryInfo"/> class.39///</summary>40///<param name="key">The key.</param>41///<param name="name">The name.</param>42///<param name="instance">The instance.</param>43public ProviderFactoryInfo(ProviderKey key, string name, object instance)44 {45 Key = key;46 Name = name;47 ExportFactory = new ExportFactory(instance);48 }4950///<summary>51/// Initializes a new instance of the <see cref="ProviderFactoryInfo"/> class.52///</summary>53///<param name="key">The key.</param>54///<param name="name">The name.</param>55///<param name="typeName">Name of the type.</param>56public ProviderFactoryInfo(ProviderKey key, string name, string typeName)57 {58 Key = key;59 Name = name;60 ExportFactory = new ExportFactory(typeName);61 }6265///</summary>66///<param name="key">The key.</param>67///<param name="name">The name.</param>68///<param name="type">The type.</param>69public ProviderFactoryInfo(ProviderKey key, string name, Type type)70 : this(key, name, type.AssemblyQualifiedName)71 {7273 }74 }View Code从代码上可以看出只要有Name和Type这2个参数即可构造⼀个ProviderFactoryInfo类的实例2.2 TypeProviderCollection 扩展的TypeProvider类型集合1 [ConfigurationCollection(typeof(TypeProvider))]2public class TypeProviderCollection : ConfigurationElementCollection, IEnumerable<ITypeProvider>3 {4///<summary>5/// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.6///</summary>7///<returns>8/// A new <see cref="T:System.Configuration.ConfigurationElement"/>.9///</returns>10protected override ConfigurationElement CreateNewElement()11 {12return new TypeProvider() as ConfigurationElement;13 }1415///<summary>16/// Gets the element key for a specified configuration element when overridden in a derived class.17///</summary>18///<param name="element">The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for.</param>19///<returns>20/// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.21///</returns>22protected override object GetElementKey(ConfigurationElement element)23 {24var provider = element as TypeProvider;2526if (provider == null)27return null;2829return ;30 }3132///<summary>33/// Returns an enumerator that iterates through the collection.34///</summary>35///<returns>36/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.37///</returns>38public new IEnumerator<ITypeProvider> GetEnumerator()39 {40int count = base.Count;4142for (int i = 0; i < count; i++)43 {44yield return (ITypeProvider)base.BaseGet(i);45 }46 }47 }View Code三 SuperSocket配置内容3.1 全局配置如图红⾊部分所⽰,SuperSocket的所有配置均包裹在SocketServiceConfig这类型中,且成为App.config的⼀个配置节点section,那么SocketServiceConfig⼜包含了什么呢? 1public partial class SocketServiceConfig : ConfigurationSection, IConfigurationSource2 {3///<summary>4/// Gets all the server configurations5///</summary>6 [ConfigurationProperty("servers")]7public ServerCollection Servers8 {9get12 }13 }1415///<summary>16/// Gets the service configurations17///</summary>18 [ConfigurationProperty("serverTypes")]19public TypeProviderCollection ServerTypes20 {21get22 {23return this["serverTypes"] as TypeProviderCollection;24 }25 }2627///<summary>28/// Gets all the connection filter configurations.29///</summary>30 [ConfigurationProperty("connectionFilters", IsRequired = false)]31public TypeProviderCollection ConnectionFilters32 {33get34 {35return this["connectionFilters"] as TypeProviderCollection;36 }37 }3839///<summary>40/// Gets the defined log factory types.41///</summary>42 [ConfigurationProperty("logFactories", IsRequired = false)]43public TypeProviderCollection LogFactories44 {45get46 {47return this["logFactories"] as TypeProviderCollection;48 }49 }5051///<summary>52/// Gets the logfactory name of the bootstrap.53///</summary>54 [ConfigurationProperty("receiveFilterFactories", IsRequired = false)]55public TypeProviderCollection ReceiveFilterFactories56 {57get58 {59return this["receiveFilterFactories"] as TypeProviderCollection;60 }61 }6263///<summary>64/// Gets the command loaders definition.65///</summary>66 [ConfigurationProperty("commandLoaders", IsRequired = false)]67public TypeProviderCollection CommandLoaders68 {69get70 {71return this["commandLoaders"] as TypeProviderCollection;72 }73 }7475///<summary>76/// Gets the max working threads.77///</summary>78 [ConfigurationProperty("maxWorkingThreads", IsRequired = false, DefaultValue = -1)]79public int MaxWorkingThreads80 {81get82 {83return (int)this["maxWorkingThreads"];84 }85 }8687///<summary>88/// Gets the min working threads.89///</summary>90 [ConfigurationProperty("minWorkingThreads", IsRequired = false, DefaultValue = -1)]91public int MinWorkingThreads92 {93get94 {95return (int)this["minWorkingThreads"];96 }97 }9899///<summary>100/// Gets the max completion port threads.101///</summary>102 [ConfigurationProperty("maxCompletionPortThreads", IsRequired = false, DefaultValue = -1)] 103public int MaxCompletionPortThreads104 {105get106 {107return (int)this["maxCompletionPortThreads"];108 }109 }110111///<summary>112/// Gets the min completion port threads.113///</summary>114 [ConfigurationProperty("minCompletionPortThreads", IsRequired = false, DefaultValue = -1)] 115public int MinCompletionPortThreads116 {117get118 {119return (int)this["minCompletionPortThreads"];120 }121 }122123///<summary>124/// Gets the performance data collect interval, in seconds.125///</summary>126 [ConfigurationProperty("performanceDataCollectInterval", IsRequired = false, DefaultValue = 60)] 127public int PerformanceDataCollectInterval128 {129get130 {131return (int)this["performanceDataCollectInterval"];132 }133 }135///<summary>136/// Gets a value indicating whether [disable performance data collector].137///</summary>138///<value>139///<c>true</c> if [disable performance data collector]; otherwise, <c>false</c>.140///</value>141 [ConfigurationProperty("disablePerformanceDataCollector", IsRequired = false, DefaultValue = false)]142public bool DisablePerformanceDataCollector143 {144get145 {146return (bool)this["disablePerformanceDataCollector"];147 }148 }149150///<summary>151/// Gets the isolation mode.152///</summary>153 [ConfigurationProperty("isolation", IsRequired = false, DefaultValue = IsolationMode.None)]154public IsolationMode Isolation155 {156get { return (IsolationMode)this["isolation"]; }157 }158159///<summary>160/// Gets the logfactory name of the bootstrap.161///</summary>162 [ConfigurationProperty("logFactory", IsRequired = false, DefaultValue = "")]163public string LogFactory164 {165get166 {167return (string)this["logFactory"];168 }169 }170171///<summary>172/// Gets the option elements.173///</summary>174public NameValueCollection OptionElements { get; private set; }175176///<summary>177/// Gets a value indicating whether an unknown element is encountered during deserialization.178/// To keep compatible with old configuration179///</summary>180///<param name="elementName">The name of the unknown subelement.</param>181///<param name="reader">The <see cref="T:System.Xml.XmlReader"/> being used for deserialization.</param>182///<returns>183/// true when an unknown element is encountered while deserializing; otherwise, false.184///</returns>185///<exception cref="T:System.Configuration.ConfigurationErrorsException">The element identified by <paramref name="elementName"/> is locked.- or -One or more of the element's attributes is locked.- or -<paramref name="elementN 186protected override bool OnDeserializeUnrecognizedElement(string elementName, System.Xml.XmlReader reader)187 {188//To keep compatible with old configuration189if (!"services".Equals(elementName, StringComparison.OrdinalIgnoreCase))190 {191if (OptionElements == null)192 OptionElements = new NameValueCollection();193194 OptionElements.Add(elementName, reader.ReadOuterXml());195return true;196 }197198var serverTypes = new TypeProviderCollection();199 reader.Read();200 serverTypes.Deserialize(reader);201202this["serverTypes"] = serverTypes;203204return true;205 }206207///<summary>208/// Gets a value indicating whether an unknown attribute is encountered during deserialization.209///</summary>210///<param name="name">The name of the unrecognized attribute.</param>211///<param name="value">The value of the unrecognized attribute.</param>212///<returns>213/// true when an unknown attribute is encountered while deserializing; otherwise, false.214///</returns>215protected override bool OnDeserializeUnrecognizedAttribute(string name, string value)216 {217const string xmlns = "xmlns";218const string xmlnsPrefix = "xmlns:";219const string xsiPrefix = "xsi:";220221//for configuration intellisense, allow these unrecognized attributes: xmlns, xmlns:*, xsi:*222if (name.Equals(xmlns) || name.StartsWith(xmlnsPrefix) || name.StartsWith(xsiPrefix))223return true;224225return false;226 }227228///<summary>229/// Gets the child config.230///</summary>231///<typeparam name="TConfig">The type of the config.</typeparam>232///<param name="childConfigName">Name of the child config.</param>233///<returns></returns>234public TConfig GetChildConfig<TConfig>(string childConfigName)235where TConfig : ConfigurationElement, new()236 {237return this.OptionElements.GetChildConfig<TConfig>(childConfigName);238 }239240 IEnumerable<IServerConfig> IConfigurationSource.Servers241 {242get243 {244return this.Servers;245 }246 }247248 IEnumerable<ITypeProvider> IConfigurationSource.ServerTypes249 {250get251 {252return this.ServerTypes;253 }254 }255256 IEnumerable<ITypeProvider> IConfigurationSource.ConnectionFilters258get259 {260return this.ConnectionFilters;261 }262 }263264 IEnumerable<ITypeProvider> IConfigurationSource.LogFactories265 {266get267 {268return this.LogFactories;269 }270 }271272 IEnumerable<ITypeProvider> IConfigurationSource.ReceiveFilterFactories273 {274get275 {276return this.ReceiveFilterFactories;277 }278 }279280281 IEnumerable<ITypeProvider> mandLoaders282 {283get284 {285return mandLoaders;286 }287 }288 }View Code1)Servers服务实例; 集合:AppServer有多少appserver实例2)ServerTypes服务类型ServerTypes 集合:继承AppServer的⼦类型3)ConnectionFilters 集合:说明了有多少个连接过滤⼯⼚类型4)LogFactories集合:说明了有多少个⽇志⼯⼚类型5)ReceiveFilterFactories 集合:说明了有多少个协议解析⼯⼚类型6)CommandLoaders 集合:说明了有多少个命令加载⼯⼚类型7)MaxWorkingThreads app最⼤⼯作线程数,主要⽤于配置ThreadPool等等,这⾥可以详细参考官⽅⽂档SuperSocket配置:其中类型的配置⽰例<serverTypes><add name="TelnetServer" type="SuperSocket.QuickStart.TelnetServer_StartByConfig.TelnetServer, SuperSocket.QuickStart.TelnetServer_StartByConfig"/ </serverTypes>均是TypeProvider,只需指定Name和type即可3.2 服务配置与之对应的类型ServerConfig,每个详细的配置均有默认值1public partial class ServerConfig : IServerConfig2 {3///<summary>4/// Default ReceiveBufferSize5///</summary>6public const int DefaultReceiveBufferSize = 4096;78///<summary>9/// Default MaxConnectionNumber10///</summary>11public const int DefaultMaxConnectionNumber = 100;121314///<summary>15/// Default sending queue size16///</summary>17public const int DefaultSendingQueueSize = 5;1819///<summary>20/// Default MaxRequestLength21///</summary>22public const int DefaultMaxRequestLength = 1024;232425///<summary>26/// Default send timeout value, in milliseconds27///</summary>28public const int DefaultSendTimeout = 5000;293031///<summary>32/// Default clear idle session interval34public const int DefaultClearIdleSessionInterval = 120;353637///<summary>38/// Default idle session timeout39///</summary>40public const int DefaultIdleSessionTimeOut = 300;414243///<summary>44/// The default send buffer size45///</summary>46public const int DefaultSendBufferSize = 2048;474849///<summary>50/// The default session snapshot interval51///</summary>52public const int DefaultSessionSnapshotInterval = 5;5354///<summary>55/// The default keep alive time56///</summary>57public const int DefaultKeepAliveTime = 600; // 60 * 10 = 10 minutes585960///<summary>61/// The default keep alive interval62///</summary>63public const int DefaultKeepAliveInterval = 60; // 60 seconds646566///<summary>67/// The default listen backlog68///</summary>69public const int DefaultListenBacklog = 100;707172///<summary>73/// Initializes a new instance of the <see cref="ServerConfig"/> class.74///</summary>75///<param name="serverConfig">The server config.</param>76public ServerConfig(IServerConfig serverConfig)77 {78 serverConfig.CopyPropertiesTo(this);7980this.Options = serverConfig.Options;81this.OptionElements = serverConfig.OptionElements;8283if (serverConfig.Certificate != null)84this.Certificate = serverConfig.Certificate.CopyPropertiesTo(new CertificateConfig());8586if (serverConfig.Listeners != null && serverConfig.Listeners.Any())87 {88this.Listeners = serverConfig.Listeners.Select(l => l.CopyPropertiesTo(new ListenerConfig())).OfType<ListenerConfig>().ToArray();89 }9091if (mandAssemblies != null && mandAssemblies.Any())92 {mandAssemblies = mandAssemblies.Select(c => c.CopyPropertiesTo(new CommandAssemblyConfig())).OfType<CommandAssemblyConfig>().ToArray();94 }95 }9697///<summary>98/// Initializes a new instance of the <see cref="ServerConfig"/> class.99///</summary>100public ServerConfig()101 {102 Security = "None";103 MaxConnectionNumber = DefaultMaxConnectionNumber;104 Mode = SocketMode.Tcp;105 MaxRequestLength = DefaultMaxRequestLength;106 KeepAliveTime = DefaultKeepAliveTime;107 KeepAliveInterval = DefaultKeepAliveInterval;108 ListenBacklog = DefaultListenBacklog;109 ReceiveBufferSize = DefaultReceiveBufferSize;110 SendingQueueSize = DefaultSendingQueueSize;111 SendTimeOut = DefaultSendTimeout;112 ClearIdleSessionInterval = DefaultClearIdleSessionInterval;113 IdleSessionTimeOut = DefaultIdleSessionTimeOut;114 SendBufferSize = DefaultSendBufferSize;115 LogBasicSessionActivity = true;116 SessionSnapshotInterval = DefaultSessionSnapshotInterval;117 }118119#region IServerConfig Members120121///<summary>122/// Gets/sets the name of the server type of this appServer want to use.123///</summary>124///<value>125/// The name of the server type.126///</value>127public string ServerTypeName { get; set; }128129130///<summary>131/// Gets/sets the type definition of the appserver.132///</summary>133///<value>134/// The type of the server.135///</value>136public string ServerType { get; set; }137138///<summary>139/// Gets/sets the Receive filter factory.140///</summary>141public string ReceiveFilterFactory { get; set; }142143///<summary>144/// Gets/sets the ip.145///</summary>146public string Ip { get; set; }147148///<summary>149/// Gets/sets the port.150///</summary>151public int Port { get; set; }152153///<summary>154/// Gets/sets the options.157158///<summary>159/// Gets the option elements.160///</summary>161public NameValueCollection OptionElements { get; set; }162163///<summary>164/// Gets/sets a value indicating whether this <see cref="IServerConfig"/> is disabled. 165///</summary>166///<value>167///<c>true</c> if disabled; otherwise, <c>false</c>.168///</value>169public bool Disabled { get; set; }170171///<summary>172/// Gets the name.173///</summary>174public string Name { get; set; }175176///<summary>177/// Gets/sets the mode.178///</summary>179public SocketMode Mode { get; set; }180181///<summary>182/// Gets/sets the send time out.183///</summary>184public int SendTimeOut { get; set; }185186///<summary>187/// Gets the max connection number.188///</summary>189public int MaxConnectionNumber { get; set; }190191///<summary>192/// Gets the size of the receive buffer.193///</summary>194///<value>195/// The size of the receive buffer.196///</value>197public int ReceiveBufferSize { get; set; }198199///<summary>200/// Gets the size of the send buffer.201///</summary>202///<value>203/// The size of the send buffer.204///</value>205public int SendBufferSize { get; set; }206207208///<summary>209/// Gets a value indicating whether sending is in synchronous mode.210///</summary>211///<value>212///<c>true</c> if [sync send]; otherwise, <c>false</c>.213///</value>214public bool SyncSend { get; set; }215216///<summary>217/// Gets/sets a value indicating whether log command in log file.218///</summary>219///<value>220///<c>true</c> if log command; otherwise, <c>false</c>.221///</value>222public bool LogCommand { get; set; }223224///<summary>225/// Gets/sets a value indicating whether clear idle session.226///</summary>227///<value>228///<c>true</c> if clear idle session; otherwise, <c>false</c>.229///</value>230public bool ClearIdleSession { get; set; }231232///<summary>233/// Gets/sets the clear idle session interval, in seconds.234///</summary>235///<value>236/// The clear idle session interval.237///</value>238public int ClearIdleSessionInterval { get; set; }239240///<summary>241/// Gets/sets the idle session timeout time length, in seconds.242///</summary>243///<value>244/// The idle session time out.245///</value>246public int IdleSessionTimeOut { get; set; }247248///<summary>249/// Gets/sets X509Certificate configuration.250///</summary>251///<value>252/// X509Certificate configuration.253///</value>254public ICertificateConfig Certificate { get; set; }255256///<summary>257/// Gets/sets the security protocol, X509 certificate.258///</summary>259public string Security { get; set; }260261///<summary>262/// Gets/sets the length of the max request.263///</summary>264///<value>265/// The length of the max request.266///</value>267public int MaxRequestLength { get; set; }268269///<summary>270/// Gets/sets a value indicating whether [disable session snapshot].271///</summary>272///<value>273///<c>true</c> if [disable session snapshot]; otherwise, <c>false</c>.274///</value>275public bool DisableSessionSnapshot { get; set; }276277///<summary>278/// Gets/sets the interval to taking snapshot for all live sessions.280public int SessionSnapshotInterval { get; set; }281282///<summary>283/// Gets/sets the connection filters used by this server instance.284///</summary>285///<value>286/// The connection filter's name list, seperated by comma287///</value>288public string ConnectionFilter { get; set; }289290///<summary>291/// Gets the command loader, multiple values should be separated by comma.292///</summary>293public string CommandLoader { get; set; }294295///<summary>296/// Gets/sets the start keep alive time, in seconds297///</summary>298public int KeepAliveTime { get; set; }299300///<summary>301/// Gets/sets the keep alive interval, in seconds.302///</summary>303public int KeepAliveInterval { get; set; }304305///<summary>306/// Gets the backlog size of socket listening.307///</summary>308public int ListenBacklog { get; set; }309310///<summary>311/// Gets/sets the startup order of the server instance.312///</summary>313public int StartupOrder { get; set; }314315///<summary>316/// Gets the child config.317///</summary>318///<typeparam name="TConfig">The type of the config.</typeparam>319///<param name="childConfigName">Name of the child config.</param>320///<returns></returns>321public virtual TConfig GetChildConfig<TConfig>(string childConfigName)322where TConfig : ConfigurationElement, new()323 {324return this.OptionElements.GetChildConfig<TConfig>(childConfigName);325 }326327///<summary>328/// Gets and sets the listeners' configuration.329///</summary>330public IEnumerable<IListenerConfig> Listeners { get; set; }331332///<summary>333/// Gets/sets the log factory name.334///</summary>335public string LogFactory { get; set; }336337///<summary>338/// Gets/sets the size of the sending queue.339///</summary>340///<value>341/// The size of the sending queue.342///</value>343public int SendingQueueSize { get; set; }344345///<summary>346/// Gets a value indicating whether [log basic session activity like connected and disconnected].347///</summary>348///<value>349///<c>true</c> if [log basic session activity]; otherwise, <c>false</c>.350///</value>351public bool LogBasicSessionActivity { get; set; }352353///<summary>354/// Gets/sets a value indicating whether [log all socket exception].355///</summary>356///<value>357///<c>true</c> if [log all socket exception]; otherwise, <c>false</c>.358///</value>359public bool LogAllSocketException { get; set; }360361///<summary>362/// Gets/sets the default text encoding.363///</summary>364///<value>365/// The text encoding.366///</value>367public string TextEncoding { get; set; }368369///<summary>370/// Gets the command assemblies configuration.371///</summary>372///<value>373/// The command assemblies.374///</value>375public IEnumerable<ICommandAssemblyConfig> CommandAssemblies { get; set; }376377#endregion378 }View Code其详细可参考代码和⽂档::重配置启动:服务实例配置3.3 IRootConfig这是最顶层的配置,从代码可以看出是对全局进⾏基础性配置,同时也是⼤部分配置实现了,如SocketServiceConfig 1public partial interface IRootConfig2 {3///<summary>4/// Gets the max working threads.。
在Keil C51 v7上针对MCS51的UcOS-II V2.51移植过程钟文青(zhongwenqing@)源码参照:(1)杨屹:ucOS51,V1.1 ()(2)ucOS-II V2.51的Keil移植(johnxliu@) ,可从ucOS-II官方网站上的下载杨屹的源码可以直接使用,特别是堆栈设计正好适合MCS51,我也没有想出更好的结构,因此沿用这种堆栈结构,就是ucOS-II的堆栈检查函数在这种结构下就没有用了。
杨屹的源码是ucOS-II V2.00版的基础上移植的,v2.51版对中断嵌套作了处理,而且也增加不少Hook函数,以及其他功能。
直接使用(2)的移植并不成功,无法直接编译使用,源码部分的小毛病不少,Keil7的setjmp.h本身就有毛病,我没运行起来,估计是堆栈部分有问题(也可能是我水平有限)。
但是其用C写ISR的方式觉得不错,移植性以及可读性好。
综合(1)、(2)的优点,我按以下步骤作了一个移植(1)将ucOS-II的大部分源码作些改动,主要是函数加上reentrant定义,将使用到data, pdata等keil C关键字的地方改动,data->ddata, pdata->ppdata。
另外还根据ucOS-II 网站公布的bug改了原来源码中的3个bug。
(2)关键的OS_CPU.H, OS_CPU_C.C, OS_CPU_A.ASM使用杨屹的为主体,将源码(2)中的定义的新Hook函数,OS_CRITICAL_METHOD的功能添加到其中。
原来杨屹的源码,OS_Enter_Critical(), OS_Exit_Critical()简单的用了EA=0,EA=1来控制中断,现在用方式3可以保留原EA的状态,可以保证在调度前不发生中断,原来的方式效率高,但如果在初始化过程中调用了OS_Exit_Critical()就打开了中断,如果期间发生中断则系统会进入一个不可知的状态。
一.为什么需要操作系统1.操作系统可以显著降低开发难度。
操作系统帮我们协调多个程序之间的耦合关系,比如我们需要将串口的接收到的数据显示在一块LCD上。
传统做法是如图1所示:图1.无操作系统流程该流程中当串口接收到数据再调用LCD显示程序将数据显示出来,而图2展示了一种基于操作系统的方法。
在该方法中串口接收数据和LCD显示程序均以为自己独占CPU,各自都只是执行自己相关部分的工作,而什么时候显示到LCD屏幕,什么时候又继续接收串口数据这个协调工作将由操作系统完成。
图2 操作系统流程从以上比较可以看出操作系统协调了不同功能程序以让他们共同完成同一个工作。
同时操作系统又隔离了各个功能程序让它们的耦合程度降低。
这样就方便设计人员编写各个功能模块,同时整个系统的结构也更加清晰。
特别是系统逻辑结构复杂,功能模块较多的情况下操作系统的这一优点体现的更加明显。
2.操纵系统让每一个任务都认为自己独占CPU,方便代码编写。
同样采用上边的例子,无操作系统情况下我么需要在适当的时候分别调用串口接收数据程序和LCD显示程序,而有操作系统时我们只需要完成两个功能模块代码然后加入到操作系统就可以了。
两个功能代码都是以无限循环的方式执行,结构显得就很简单。
3.操作系统增加代码的移植性。
这一点我认为在ucOS系统上体现得并不明显,对于其他系统例如android,linux等系统可以这样讲,因为他们基本上应该算是一个中等复杂系统,而ucOS是一个简单嵌入式系统。
对于一个中等复杂系统它的底层硬件设备是有一定要求的,例如android 设备,根据系统特性它就需要有GPS支持,显示屏支持,电子罗盘支持,摄像头支持这些支持都被列入android设备的系统内,它们以驱动的形式存在。
而上层的应用程序通过调用底层的支持进而实现复杂的功能。
而ucOS我认为它仅仅只是一个调度器,他的工作就是协调多个应用程序在单个MCU上"同时"运行而已,它几乎是没有驱动这个概念的。
免费的!MICROSOFT SPEECH SDK 5.1\INCLUDEMICROSOFT SPEECH SDK 5.1\LIB以上两个目录是教程里面提到的,可以不使用,一样可以编译第一节课新建MFC工程,单文档模式,基类用CListView,其余默认即可打开gh0stView.cpp找到void CGh0stView::OnInitialUpdate()函数新建一个结NONCLIENTMETRICS ncm;NONCLIENTMETRICS这个结构就包含了非客户区的一些属性对ncm变量进行初始化memset(&ncm, 0, sizeof(NONCLIENTMETRICS));对这个结构的成员函数进行设置ncm.cbSize = sizeof(NONCLIENTMETRICS); //指定了ncm的大小使用宏VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS), &ncm,0));其目的是方便调试,在Debug版本中,如果计算的表达式为0则中断程序,并打印出错误信息,如果在Release版本中,出现表达式为0的时候,则不做任何的处理,当没有发生::SystemParametersInfo调用系统函数,查询或是设置系统参数,或是修改用户的一个外观,返回值是一个BOOL类型第一个参数是获取非客户区参数第二个参数是整个的非客户区结构的大小第三个参数是将获得到的信息保存在ncm这个地址中第四个参数由于是为了获取信息写0即可,如果是设置信息为目的,就需要换成其它参考MSDN第二节课在gh0stView.h中声明一个私有成员变量公有成员可以被所有类访问受保护成员只能在类内部或其子类可以访问私有成员只能在类内部访问,其子类是不可以访问的private:CListCtrl* m_pListCtrl;私有的列表控件的指针,为什么要声明这个呢,我们之前提到了基类是CListView,因此在这个里声明了一个指针CPP是执行文件,H是头文件接下来对我们在CPP文件中声明的私有成员变量进行赋值m_pListCtrl=&GetListCtrl();GetListCtrl()这个函数的原型是CListView::GetListCtrlCListCtrl& GetListCtrl() const; 得到一个和视图相关联的一个列表控件的引用引用的使用方法:引用相当于是一个别名,周瑜和周公谨是一个人,引用和变量也相当于是一个东西int m;int &n = m; //为变量m定义了一个引用n,m是被引用,对n的操作就相当于对m来进行操作了,这里n既不是m的一个拷贝,又不是指向m的一个指针,而n就是m,作用就是用于函数的型参和返回值上,引用也是使用了一个地址传递的方式,比值传递的速度要快指针与引用的区别:主要是吴国的水军大都督是周瑜,那么这个吴国的水军大都督可看成是一个指针,引用被创建的时候是必须要进行初始化的,而指针是在任何时候被初始化的另一个引用不可以是NULL,必须有一个合法的存储单位和引用相关联,而指针是可以有NULL的。
modernwms源码解读标题:ModernWMS源码解读引言概述:ModernWMS是一款现代化的仓储管理系统,其源码的解读对于深入理解系统的设计和实现非常重要。
本文将对ModernWMS源码进行解读,从五个大点来详细阐述其核心功能和实现原理。
正文内容:1. 数据库设计1.1 数据库结构:详细介绍ModernWMS的数据库结构,包括表的关系、字段的含义以及索引的使用。
1.2 数据库连接:解释ModernWMS如何与数据库进行连接,包括连接池的使用、事务管理等。
2. 用户管理2.1 用户注册与登录:详细介绍ModernWMS的用户注册和登录功能的实现原理,包括加密算法、验证码的生成与验证等。
2.2 权限管理:解析ModernWMS的权限管理系统,包括角色的定义、权限的分配与控制等。
2.3 用户信息管理:介绍ModernWMS中用户信息的管理,包括个人资料的修改、密码重置等。
3. 仓库管理3.1 仓库信息管理:详细解读ModernWMS中仓库信息的管理,包括仓库的增删改查、仓库状态的控制等。
3.2 库位管理:介绍ModernWMS中库位的管理,包括库位的分配、库存的调整等。
3.3 库存管理:解析ModernWMS中库存的管理,包括库存的盘点、入库和出库等。
4. 订单管理4.1 订单生成:详细介绍ModernWMS中订单的生成,包括订单的类型、状态的定义与管理等。
4.2 订单处理:解析ModernWMS中订单的处理流程,包括订单的分配、拣货、打包等。
4.3 订单查询与统计:介绍ModernWMS中订单的查询与统计功能,包括按时间、客户等条件进行查询与统计。
5. 报表与分析5.1 报表生成:详细介绍ModernWMS中报表的生成,包括报表的模板设计、数据获取与展示等。
5.2 数据分析:解析ModernWMS中数据分析功能的实现原理,包括数据的提取、处理与展示等。
5.3 绩效评估:介绍ModernWMS中绩效评估的方法与指标,包括订单处理效率、库存周转率等。
狗拿耗子1lwip ———狗拿耗子第四篇1、lwip的背景lwip是Swedish Institute of Computer Science开发的用于嵌入式系统的TCPIP协议栈从网上的评论看似乎用的人不少。
它的实现是应该参考了BSD的实现在介绍TCP的时候大家就会发现其拥塞控制的实现算法机会与BSD的一模一样。
lwip的整个代码写的比YASS2差一截难以入手介绍我打算按照TCP的server与client的角度分别走一遍代码。
lwip的内核运行在同一个任务中lwip提供的系统调用通过mailbox与内核进行通信然后用户阻塞在一个专门的mailbox上内核完成用户的请求后post 该mailbox用户得以继续执行。
有的协议栈的实现却是每层跑在一个任务中这样层与层间的相互调用将会引起上下文的切换。
更重要的是lwip可以运行在裸机的环境中即不需要操作系统的支持。
这对一些低成本的设备还是很具有吸引力的。
lwip的官方网站为/projects/lwip/目前最新的版本是1.3.0而本文参考的是1.2.0。
2、netconn_new系统调用2.1 相关的数据结构enum netconn_type NETCONN_TCP NETCONN_UDP NETCONN_UDPLITENETCONN_UDPNOCHKSUM NETCONN_RAW struct netconn enumnetconn_type type enum netconn_state state union struct tcp_pcb tcp struct udp_pcb udp struct raw_pcb raw pcb err_t err sys_mbox_t mbox sys_mbox_t recvmboxsys_mbox_t acceptmbox sys_sem_t sem int socket u16_t recv_avail void callbackstruct netconn enum netconn_evt u16_t len 狗拿耗子2 struct netconn用一个union将udp、tcp、raw的pcb包含起来实现由netconn到不同协议的分发这是c语言编程的一个常用技巧。
UC_OSII学习笔记是⼀个可以基于ROM运⾏的、可裁减的、抢占式、实时、多任务OS内核;可剥夺型的实时内核在任何时候都运⾏就绪了的最⾼优先级的任务。
⼀个任务,也称作⼀个线程,是⼀个简单的程序,该程序可以认为 CPU 完全只属该程序⾃⼰。
OS包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。
没有提供输⼊输出管理,⽂件系统,⽹络等额外的服务。
但由于uC/OS-II良好的可扩展性和源码开放,这些⾮必须的功能完全可以由⽤户⾃⼰根据需要分别实现。
当任务执⾏完毕后(时间⽚到),他把⾃⼰的CPU寄存器所有内容保存到⾃⼰的堆栈中,同时把CPU让给别的任务,那么得到CPU使⽤权的任务把⾃⼰的CPU寄存器从⾃⼰的堆栈中放到真正的CPU寄存器中开始运⾏,就这样周⽽复始。
任务管理:建⽴任务时的优先级、堆栈时间管理:通过定时中断来实现的内存管理:给⼀个⾸地址、块⼤⼩、块数⽬。
将连续地址数组链表化。
获取:指定⼀个内存控制块,返回链表⾸部内存块地址,链表指针移到下⼀个空闲内存块;释放:指定⼀个内存控制块以及要释放的内存块⾸地址。
该内存块存放链表⾸个空闲内存块地址,并将⾃⼰赋值为⾸个空闲内存块。
邮箱:各个任务把⾃⼰的数据封装后以邮箱的形式发送给其它的任务使⽤,从⽽达到任务间通信的⽬的。
⼀个指针型的变量,通常该指针指向⼀个包含了“消息”的特定数据结构。
1、µC/OS-II 是多任务,⽽且为每个任务开辟⼀个堆栈2、µC/OS-II要⽤户在使⽤任何服务之前先调⽤ OSInit() [L1.5(2)]。
它会建⽴两个任务:空闲任务和统计任务,前者在没有其它任务处于就绪态时运⾏;后者计算 CPU 的利⽤率。
3、在启动多任务OSStart() 之前⽤户⾄少要先建⽴⼀个任务4、要使⽤堆栈检查操作必须⽤ OSTaskCreateExt()建⽴任务5、OSMemCreate()函数建⽴并初始化⼀块内存区。
[AbpvNext源码分析]-20.电⼦邮件与短信⽀持⼀、简介ABP vNext 使⽤ Volo.Abp.Sms 包和 Volo.Abp.Emailing 包将短信和电⼦邮件作为基础设施进⾏了抽象,开发⼈员仅需要在使⽤的时候注⼊ ISmsSender 或 IEmailSender 即可实现短信发送和邮件发送。
⼆、源码分析2.1 启动模块短信发送的抽象层⽐较简单,AbpSmsModule 模块内部并⽆任何操作,仅作为空模块进⾏定义。
电⼦邮件的 AbpEmailingModule 模块内,主要添加了⼀些本地化资源⽀持。
另⼀个动作就是添加了⼀个 BackgroundEmailSendingJob 后台作业,这个后台作业主要是⽤于后续发送电⼦邮件使⽤。
因为邮件发送这个动作实时性要求并不⾼,在实际的业务实践当中,我们基本会将其加⼊到⼀个后台队列慢慢发送,所以这⾥ ABP 为我们实现了BackgroundEmailSendingJob。
BackgroundEmailSendingJob.cs:public class BackgroundEmailSendingJob : AsyncBackgroundJob<BackgroundEmailSendingJobArgs>, ITransientDependency{protected IEmailSender EmailSender { get; }public BackgroundEmailSendingJob(IEmailSender emailSender){EmailSender = emailSender;}public override async Task ExecuteAsync(BackgroundEmailSendingJobArgs args){if (args.From.IsNullOrWhiteSpace()){await EmailSender.SendAsync(args.To, args.Subject, args.Body, args.IsBodyHtml);}else{await EmailSender.SendAsync(args.From, args.To, args.Subject, args.Body, args.IsBodyHtml);}}}这个后台任务的逻辑也不复杂,就使⽤ IEmailSender 发送邮件,我们在任何地⽅需要后台发送邮件的时,只需要注⼊ IBackgroundJobManager,使⽤BackgroundEmailSendingJobArgs 作为参数添加⼊队⼀个后台作业即可。
2******************************************************************************************** *************3 * uC/OS-II实时控制内核4 * 消息邮箱管理5 * 文件 : OS_MBOX.C 消息邮件管理代码6 * 作者 : Jean J. Labrosse7 * 中文注解: 钟常慰 zhongcw @ 译注版本:1.0 请尊重原版内容8******************************************************************************************** *************9 */1011 #ifndef OS_MASTER_FILE //是否已经定义OS_MASTER_FILE12 #include "includes.h" //包含"includes.h"文件13 #endif //结束定义1415 #if OS_MBOX_EN > 0 //条件编译允许(1)产生消息邮箱相关代码16 /*17******************************************************************************************** *************18 * 查看指定的消息邮箱是否有需要的消息(ACCEPT MESSAGE FROM MAILBOX)19 *20 * 描述: OSMboxAccept()函数查看指定的消息邮箱是否有需要的消息。
不同于OSMboxPend()函数,如果没有需要的消息,21 * OSMboxAccept()函数并不挂起任务。
如果消息已经到达,该消息被传递到用户任务并且从消息邮箱中清除。
通22 * 常中断调用该函数,因为中断不允许挂起等待消息。
23 *24 * 意见: pevent 是指向需要查看的消息邮箱的指针。
当建立消息邮箱时,该指针返回到用户程序。
25 * (参考OSMboxCreate()函数)。
26 *27 * 返回: 如果消息已经到达,返回指向该消息的指针;如果消息邮箱没有消息,返回空指针。
28 *29 * 注意: 必须先建立消息邮箱,然后使用。
30******************************************************************************************** *************31 */3233 #if OS_MBOX_ACCEPT_EN > 0 //允许(1)生成 OSMboxAccept()代码34 void *OSMboxAccept (OS_EVENT *pevent) //查看消息邮箱(消息邮箱指针)36 #if OS_CRITICAL_METHOD == 3 //中断函数被设定为模式337 OS_CPU_SR cpu_sr;38 #endif39 void *msg; //定义消息邮箱内容的指针404142 #if OS_ARG_CHK_EN > 0 //所有参数必须在指定的参数内43 if (pevent == (OS_EVENT *)0) { //当消息邮箱指针为NULL时,返回0,空指针44 return ((void *)0);45 }46 if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { //当事件类型≠消息邮箱类型47 return ((void *)0); //返回空指针48 }49 #endif50 OS_ENTER_CRITICAL(); //关闭中断51 msg = pevent->OSEventPtr; //取消息邮箱中的内容52 pevent->OSEventPtr = (void *)0; //将消息邮箱的内容清053 OS_EXIT_CRITICAL(); //打开中断54 return (msg); //返回消息,如果为空,说明没有消息;不为空,说明有内容55 }56 #endif57 /*$PAGE*/58 /*59******************************************************************************************** *************60 * 建立并初始化一个消息邮箱(CREATE A MESSAGE MAILBOX)61 *62 * 描述: 建立并初始化一个消息邮箱。
消息邮箱允许任务或中断向其他一个或几个任务发送消息。
63 *64 * 参数: msg 参数用来初始化建立的消息邮箱。
如果该指针不为空,建立的消息邮箱将含有消息。
65 *66 * 返回: 指向分配给所建立的消息邮箱的事件控制块的指针。
如果没有可用的事件控制块,返回空指针。
67 *68 * 注意: 必须先建立消息邮箱,然后使用。
69******************************************************************************************** *************70 */7172 OS_EVENT *OSMboxCreate (void *msg) //建立并初始化一个消息邮箱(msg 参数不为空含内容)73 {74 #if OS_CRITICAL_METHOD == 3 //中断函数被设定为模式375 OS_CPU_SR cpu_sr;76 #endif__77 OS_EVENT *pevent; //定义一个指向事件控制块的指针787980 if (OSIntNesting > 0) { //中断嵌套数>0时,表示还有中断任务在运行81 return ((OS_EVENT *)0); //返回082 }83 OS_ENTER_CRITICAL(); //关闭中断84 pevent = OSEventFreeList; //pevent=空余事件管理列表85 if (OSEventFreeList != (OS_EVENT *)0) { //如果有空余事件管理块86 OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;87 } //空余事件控制链表指向下一个空余事件控制块88 OS_EXIT_CRITICAL(); //打开中断89 if (pevent != (OS_EVENT *)0) { //如果有空余的事件控制块可用90 pevent->OSEventType = OS_EVENT_TYPE_MBOX; //则这个类型=消息邮箱类形91 pevent->OSEventPtr = msg; //将初始值存入事件管理块ECB中92 OS_EventWaitListInit(pevent); //初始化一个事件控制块93 }94 return (pevent); //返回该详细邮箱(事件)的指针,即邮箱句柄95 }96 /*$PAGE*/97 /*98******************************************************************************************** *************99 * 删除消息邮箱 (DELETE A MAIBOX)100 *101 * 描述: 删除消息邮箱。
因为多任务可能会试图继续使用已经删除了的邮箱,故调用本函数有风险。
使用本函数102 * 须特别小心。
一般的说,删除邮箱之前,应该首先删除与本邮箱有关的任务。
103 *104 * 描述: pevent 指向邮箱得指针.该指针是在邮箱建立时,返回给用户应用程序的指针.(参考OSMboxCreate())105 *106 * opt 该选项定义邮箱的删除条件:107 * opt == OS_DEL_NO_PEND 可以选择只能在已经没有任何任务在等待该邮箱的消息时,才能删除邮箱;108 * opt == OS_DEL_ALWAYS 不管有没有任务在等待邮箱的消息,立即删除邮箱。
109 * -->第2种情况下,所有等待邮箱消息的任务都立即进入就绪态。
110 *111 * err 指向错误代码的指针,返回出错代码可以是以下几种之一:112 * OS_NO_ERR 调用成功,邮箱已经删除;113 * OS_ERR_DEL_ISR 试图在中断服务子程序中删除邮箱;114 * OS_ERR_INVALID_OPT 无效的opt参数,用户没有将opt定义为上述2种情况之一;115 * OS_ERR_TASK_WAITING 一个或更多的任务在等待邮箱的消息;116 * OS_ERR_EVENT_TYPE pevent不是指向邮箱的指针;117 * OS_ERR_PEVENT_NULL 已经没有OS_EVENT数据结构可以使用。
118 *119 * 返回: pevent 返回空指针NULL,表示邮箱已被删除,返回pevent,表示邮箱没有删除,在这种情况下,应该进一步120 * 查看出错代码,找到出错原因。
121 *122 * 注意: 1) 使用这个函数调用时,须特别小心。
因为其他任务可能还要用这个邮箱。
123 * 2) 当挂起的任务进入就绪态时,中断是关闭的,这就意味着中断延迟时间与在等待邮箱的消息的任务数有关。
124 * 3) 调用OSMboxAccept()函数也不可能知道邮箱是否已经被删除了。
125******************************************************************************************** *************126 */127128 #if OS_MBOX_DEL_EN > 0 //允许(1)生成 OSMboxDel()代码129 //删除消息邮箱(消息邮箱指针、删除条件、出错代码指针)130 OS_EVENT *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)131 {132 #if OS_CRITICAL_METHOD == 3 //中断函数被设定为模式3133 OS_CPU_SR cpu_sr;134 #endif135 BOOLEAN tasks_waiting; //定义布尔量,任务等待条件136137138 if (OSIntNesting > 0) { //中断嵌套数>0时,表示还有中断任务在运行139 *err = OS_ERR_DEL_ISR; //错误等于(试图在中断程序中删除一个信号量事件)140 return (pevent); //返回消息邮箱指针141 }142 #if OS_ARG_CHK_EN > 0 //所有参数在指定的范围之内143 if (pevent == (OS_EVENT *)0) { //当消息邮箱指针为NULL,即0(空)144 *err = OS_ERR_PEVENT_NULL; //错误等于(已经没有可用的OS_EVENT数据结构了)145 return (pevent); //返回消息邮箱指针146 }147 if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { //当事件类型不否是消息邮箱类型148 *err = OS_ERR_EVENT_TYPE; //pevent指针不是指向消息邮箱149 return (pevent); //返回消息邮箱指针150 }151 #endif152 OS_ENTER_CRITICAL(); //关闭中断153 if (pevent->OSEventGrp != 0x00) { //事件等待标志,索引值≠0,有任务在等待154 tasks_waiting = TRUE; //有任务在等待=1(TRUE真)155 } else {156 tasks_waiting = FALSE; //否则,没有任务在等待=0,(FALSE假)157 }158 switch (opt) { //条件选择159 case OS_DEL_NO_PEND: //1)没有任务在等待该消息邮箱160 if (tasks_waiting == FALSE) { //如果没有事件在等待161 pevent->OSEventType = OS_EVENT_TYPE_UNUSED; //事件类型=空闲162 pevent->OSEventPtr = OSEventFreeList; //信号量对应的指针=空余块链接表163 OSEventFreeList = pevent; //空余块链接表=当前事件指针164 OS_EXIT_CRITICAL(); //关闭中断165 *err = OS_NO_ERR; //错误等于(成功删除)166 return ((OS_EVENT *)0); //返回0167 } else { //否则,有任务在等待168 OS_EXIT_CRITICAL(); //打开中断169 *err = OS_ERR_TASK_WAITING; //错误等于(有一个或一个以上的任务在等待消息邮箱) 170 return (pevent); //返回消息邮箱指针171 }172173 case OS_DEL_ALWAYS: //2)多任务等待,尽管有任务在等待,还是要删除174 while (pevent->OSEventGrp != 0x00) { //等待标志≠0,还是要删除175 //OS_EventTaskRdy()函数将最高级优先级任务从等待列表中删除176 OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX); //使一个任务进入就绪态177 }178 pevent->OSEventType = OS_EVENT_TYPE_UNUSED; //事件类型=空闲179 pevent->OSEventPtr = OSEventFreeList; //消息邮箱对应的指针=空余块链接表180 OSEventFreeList = pevent; //空余块链接表=当前事件指针181 OS_EXIT_CRITICAL(); //关闭中断182 if (tasks_waiting == TRUE) { //当任务等待=1,真183 OS_Sched(); //任务调度,最高优先级进入运行状态184 }185 *err = OS_NO_ERR; //错误等于(成功删除)186 return ((OS_EVENT *)0); //返回0187188 default: // 3)当以上两种情况都不是189 OS_EXIT_CRITICAL(); //关闭中断190 *err = OS_ERR_INVALID_OPT; //错误等于(没有将opt参数定义为2种合法的参数之一) 191 return (pevent); //返回信号量指针192 }193 }194 #endif195196 /*$PAGE*/197 /*198******************************************************************************************** *************199 * 任务等待消息(PEND ON MAILBOX FOR A MESSAGE)200 *201 * 描述: 用于任务等待消息。