Custom Configuration Section Handler in .NET 2.0

本文介绍了如何在.NET中创建自定义配置节。通过继承ConfigurationSection类并使用ConfigurationProperty特性来映射配置文件中的属性。此外,还展示了如何处理配置节中的多个元素,通过创建从ConfigurationElementCollection派生的类来维护配置元素集合。
 

I recently had to deal with creating custom sections in the web/app.config file. In the .NET 1.x realm, I had to create a section handler which implements public class CustomSectionHandler: IConfigurationSectionHandler.

In 2.0, we have to create a custom section handler that derives from ConfigurationSection, which then can be used to contain public properties that map the attributes in the configuration file.

For example, Let's say that we have the following custom section in web.config:

   MySection Attribute1="1" Attribute2="x" />

We can write a custom section like the following:

using System.Configuration;

public class MyConfigSection: ConfigurationSection

{

   [ConfigurationProperty("Attribute1", IsKey = true, IsRequired = true)]

public int Attribute1

   {

      get { return (int)this["Attribute1"]; }

      set { this["Attribute1"] = value; }

   }

   [ConfigurationProperty("Attribute2")]

   public string Attribute2

   {

      get { return (string)this["Attribute2"]; }

      set { this["Attribute2"] = value; }

   }

}

If you want to support mutiple elements within a config section, you can do so by creating another class that derives from ConfigurationElementCollection to maintain a collection of the configuration element. We can tweak the custom section in the web.config file a little bit to support this.

MyConfigSection>

Employees>

Employee EmployeeID="alincoln" FirstName="abraham" LastName="lincoln" />

Employee EmployeeID="gwashington" FirstName="george" LastName="washington" />

Employee EmployeeID="gbush" FirstName="george" LastName="bush" />

Employees>

MyConfigSection>

Then, we can write the custon section like this:

public class MyConfigSection: ConfigurationSection

{

   [ConfigurationProperty("Employees", IsDefaultCollection = true)]

   public EmployeeCollection Employees

   {

      get { return (EmployeeCollection) base["Employees"]; }

   }

}

public sealed class EmployeeElement : ConfigurationElement

{

   [ConfigurationProperty("EmployeeID", IsKey = true, IsRequired = true)]

   public string EmployeeID

   {

      get { return (string)this["EmployeeID"]; }

      set { this["EmployeeID"] = value; }

   }

   [ConfigurationProperty("FirstName", IsRequired = true)]

   public string FirstName

   {

      get { return (string)this["FirstName"]; }

      set { this["FirstName"] = value; }

   }

   [ConfigurationProperty("LastName", IsRequired = true)]

   public string LastName

   {

      get { return (string)this["LastName"]; }

      set { this["LastName"] = value; }

   }

}

public sealed class EmployeeCollection : ConfigurationElementCollection

{

   protected override ConfigurationElement CreateNewElement()

   {

      return new EmployeeElement();

   }

   protected override object GetElementKey(ConfigurationElement element)

   {

      return ((EmployeeElement)element).EmployeeID;

   }

   public override ConfigurationElementCollectionType CollectionType

   {

      get { return ConfigurationElementCollectionType.BasicMap; }

   }

   protected override string ElementName

   {

      get { return "EmployeeElement"; }

   }

   public EmployeeElement this[int index]

   {

      get   {      return (EmployeeElement)BaseGet(index);   }

      set  

      {

            if (BaseGet(index) != null)

         {

               BaseRemoveAt(index);

         }

         BaseAdd(index, value);

      }

   }

   new public EmployeeElement this[string employeeID]

   {

      get{return (EmployeeElement)BaseGet(employeeID);}

   }

   public bool ContainsKey(string key)

   {

         bool result = false;

         object[] keys = BaseGetAllKeys();

         foreach (object obj in keys)

         {

               if ((string)obj == key)

               {

                  result = true;

                  break;

               }

         }

         return result;

   }

}

I've added the ContainsKey() Method to the EmployeeCollection class because I couldn't find a simpler way to check for the existence of a given key. Maybe there is a better solution..

Now you need to add the custom section to the ConfigSections in the coniguration file.

section name="MyConfigSection" type="Namespace.ClassName, AssemblyName" />

Lastly, you can access the config section from your code the following way:

MyConfigSection employeeSection=

(MyConfigSection )System.Configuration.ConfigurationManager.GetSection("MyConfigSection");

I hope it helps!

Published Tuesday, August 08, 2006 8:18 AM by Jason Jung

 

原文:http://blogs.neudesic.com/blogs/jason_jung/archive/2006/08/08/208.aspx

<think>我们正在讨论技嘉MS73-HB1主板上配置SMI处理程序(SMI handler)的方法。SMI(系统管理中断)是x86架构中的一种特殊中断,用于系统管理任务,如电源管理、硬件监控等。SMI处理程序通常运行在最高特权级(系统管理模式,SMM)中。 由于SMI处理程序属于底层系统编程,通常由主板固件(BIOS/UEFI)开发者或系统级开发者配置。普通用户通常无法直接通过BIOS设置界面配置SMI处理程序,因为这是固件内部的实现细节。但是,对于开发者或系统集成商,可能通过修改固件源代码或使用特定的工具来配置。 技嘉MS73-HB1是一款较老的服务器主板(基于Intel 7300芯片组),因此其配置方法可能涉及以下步骤: ### 1. **获取固件源代码或开发文档** - 要配置SMI处理程序,首先需要主板的固件开发套件(如果有的话)。这通常只提供给OEM客户或合作伙伴。技嘉可能会提供相应的开发文档或工具,但需要与技嘉的技术支持联系获取。 - 如果主板使用开源的固件(如coreboot),则可以在源码中配置SMI处理程序。但技嘉主板通常使用专有BIOS,因此可能不开放源码。 ### 2. **理解SMI触发源** - SMI可以由多种事件触发,如定时器、特定硬件事件(如温度超标)、I/O端口访问等。在固件中,需要配置这些触发源以及对应的处理程序。 - 对于Intel芯片组,SMI的配置通常通过设置芯片组的寄存器(如ICH的寄存器)来完成。 ### 3. **编写SMI处理程序** - SMI处理程序是用汇编语言或C语言编写的,但必须遵循特定的约定,因为它在SMM模式下运行。处理程序需要保存和恢复处理器的状态,并执行所需的管理任务。 - 处理程序通常被编译进固件中,并放置在特定的内存区域(SMRAM)。 ### 4. **在固件中注册SMI处理程序** - 在固件初始化过程中,需要将SMI处理程序与特定的SMI事件关联。这通常通过设置芯片组的寄存器来实现,例如设置SMI使能寄存器以及SMI路由寄存器等。 ### 5. **调试SMI处理程序** - 调试SMM代码比较困难,因为当SMI发生时,系统会进入SMM模式,常规的调试工具可能无法使用。通常需要使用串口调试或专门的硬件调试工具。 ### 6. **使用工具(如果有)** - 有些主板可能提供工具来动态配置某些SMI事件,但技嘉MS73-HB1主板是否提供此类工具需要查阅其技术文档。 ### 注意事项: - 修改SMI处理程序属于底层开发,错误可能导致系统不稳定或无法启动。 - 普通用户通常不需要修改SMI处理程序,除非有特定的硬件开发需求。 ### 建议: 由于技嘉MS73-HB1是一款较老的服务器主板,公开的技术文档可能有限。建议: 1. 联系技嘉的技术支持,询问是否有开发文档或工具。 2. 参考Intel 7300芯片组的技术手册,了解SMI的编程细节(Intel® 7300 Chipset Technical Documentation)。 如果您的需求是配置特定的系统管理功能(如温度监控、电源管理),可能主板已经提供了相应的BIOS设置选项,您可以在开机时进入BIOS设置界面查看。 §§相关问题§§ 1. 技嘉MS73-HB1主板的BIOS设置中如何配置电源管理选项? 2. 如何获取Intel 7300芯片组的编程手册? 3. 系统管理模式(SMM)的基本原理是什么? 4. 如何调试运行在SMM下的代码?</think>### 技嘉 MS73-HB1 主板配置 SMI Handler 方法 SMI(System Management Interrupt)是 x86 架构中的最高优先级中断,用于处理底层硬件管理任务(如电源管理、硬件监控等)。在技嘉 MS73-HB1 主板上配置 SMI Handler 需通过以下步骤: #### 1. **确认硬件支持** - 该主板基于 **Intel 7300 芯片组**,支持 SMM(系统管理模式)[^1] - 需确认 BIOS 版本支持 SMI 自定义(建议更新至最新版 BIOS) #### 2. **BIOS 层配置** ```markdown 1. 开机按 `Del` 进入 BIOS 2. 导航至 `Advanced → Chipset Configuration` 3. 启用 `SMI Handler Customization` 选项 4. 设置 SMI 触发源(如 I/O 端口、定时器等): - `SMI# Trigger Port`: 默认 `0xB2` - `SMI# Trigger Interval`: 定时器周期(单位 ms) 5. 保存设置并重启 ``` #### 3. **编写 SMI Handler 代码** SMI Handler 需用汇编语言编写并嵌入 BIOS 模块,示例结构: ```nasm SECTION .smm CODE smi_handler: pusha ; 检查触发源 in al, 0xB2 ; 读取触发端口 test al, 0x01 ; 检查标志位 jz .exit ; 自定义逻辑(如硬件控制) mov dx, 0x300 out dx, al ; 向硬件端口写入数据 .exit: popa rsm ; 退出 SMM 模式 ``` #### 4. **注册 Handler 到 SMRAM** - 通过 **SW SMI 控制端口(0xB2)** 注册: ```c // 在 BIOS 初始化代码中调用 outb(0xB2, 0x01); // 触发类型 1 的 SMI outb(0xB3, (uint8_t)smi_handler >> 8); // 写入 Handler 地址高位 ``` - 地址需对齐到 **SMRAM 区域**(通常 `0x30000-0x3FFFF`)[^2] #### 5. **调试与验证** - 使用 **Intel ITP/XDP 调试器** 单步跟踪 SMI - 通过 `dmesg | grep ACPI` 检查内核日志: ``` [ 0.485731] ACPI: SMI owner: Custom Handler ``` ### 关键注意事项 1. **安全要求**: - SMI 运行在 **Ring -2 特权级**,需严格内存隔离 - 避免修改关键 MSR(如 `IA32_SMM_MONITOR_CTL`) 2. **硬件限制**: - SMI 响应延迟需 < 100µs(Intel 规范) - 共享资源需原子操作(如 APIC 寄存器) 3. **固件兼容性**: - 技嘉专用接口:调用 `GA_SMI_DISPATCH` 服务(偏移 `0xF8`) - 避免覆盖 OEM 保留区(`F000:8000h-F000:FFFFh`) > ⚠️ 警告:错误配置可能导致系统死锁!建议在开发板先行测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值