65.9K
CodeProject 正在变化。 阅读更多。
Home

实时性。Windows 在 Ring2 (x86 32 位操作系统) 中运行

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.14/5 (25投票s)

2007年9月2日

CPOL

2分钟阅读

viewsIcon

145915

downloadIcon

3337

本文介绍了 Hadcon 针对 Windows 7/XP 的实时模块

引言

由于各种商业和技术原因,Microsoft Windows Vista、XP/2000 操作系统越来越多地被认为是部署实时系统的平台。原因包括:

  1. 该平台上有许多可用的应用程序
  2. 该平台上有多种可用的开发工具
  3. Microsoft Win32 应用程序编程接口 (API) 的丰富性
  4. 大量开发人员、支持人员和最终用户熟悉该系统

Hadcon 的实时模块 (RTM) 的开发旨在为 Windows 带来“硬”实时功能(例如创建计时器、系统线程,以及资源管理——内存、端口、中断),而无需创建驱动程序。

RTM 架构

在实时系统中,事件的精确执行至关重要。RTM 为开发人员提供了完全的灵活性,以确定其系统的适当计时器分辨率。定时器间隔值可以设置在 100 微秒到 1 毫秒之间 (100,200,500,1000)。 计时器间隔默认位于 [AddNewInst] 部分 rtmdrv.inf 文件的 HKR,,TimerQuantum,,500 中。

RTM 使用“混合”代码,即,计时器、中断例程(在 Ring 0 中工作)和用户例程(在 Ring 3 中工作)都集成在一个 DLL 模块中。
实时组件(计时器、系统线程和中断例程)必须锁定在内存中,以避免由于页面错误而造成的延迟。 因此,RTM 使用 data_segcode_segbss_seg 编译指示定义其自己的节,用于定位代码、数据和堆栈。

//
//
#pragma code_seg( "RTMCODE ")

Specifies a code section where functions are to be allocated.
For example:

#pragma code_seg( "RTMCODE ")

void timer1(unsigned dwmess )
{
/*
code
*/
..................
}

#pragma code_seg()

#pragma data_seg( "RTMDATA ")

Specifies a code section where initialized data are to be allocated.
For example:

#pragma data_seg( "RTMDATA ")

char buff[10] = {0};
int k1 = 0;

#pragma data_seg()

#pragma bss_seg( "RTMBSS ")

char buff[10];
int k1;

#pragma bss_seg()

计时器

RTM 使用系统计时器。 系统计时器以每毫秒一个节拍(或 100、200、500 微秒)的固定速率生成系统节拍,这是计时器中断被生成并由操作系统(中断服务例程 ISR)处理的速率。
RTmCreateTimer 函数允许您将处理例程附加到计时器中断,就像 RTM 计时器例程允许您将处理例程与给定的计时器到期关联一样。
RTM 计时器不是同步对象,这意味着线程无法等待具有 RTM 计时器句柄的单个对象。

这与 Windows 可等待计时器形成对比,Windows 可等待计时器是一个线程可以等待的对象,或者线程可以接收通知的对象。

示例代码

#pragma code_seg( "RTMCODE ")
//
//
void timer1(unsigned dwmess )
{
 int i;
 unsigned nstate;
 unsigned nvalue;
 unsigned short ndigport;

      if(nstop ) return ;

      if(initLpt == 0)
      {
       _asm {
         mov dx,378h
         mov ax,0
         out dx,ax ;//outp(BASE_LPT,0);
         add dx,2; CR
         mov ax,2eh
         out dx,ax ;//outp(BASE_LPT+CR,0x2e);
      }
      initLpt =1;

      rtmsqrt(1.5);
/*
code
*/
..................

}

#pragma code_seg()

void func()
{
  int error;
  HANDLE tm;

       if(RtmInit(hRTMDLL,KERNEL_MODE) == -1) return 0;

         RtmDebug(hRTMDLL ,TRUE);
         tm = RtmCreateTimer
            (hRTMDLL ,timer_anl,0x2000,stanl.quantum,KERNEL_MODE);
         RtmStartTimer(hRTMDLL ,tm,0x3000);
         error = RtmTimerPostMessage(hRTMDLL ,tm,0x100);
}

使用线程

RtmCreateThread 函数创建一个系统线程(参见:Windows XP/2000 的 DDK 中的 PsCreateSystemThread)。
您可以使用 KeSetPriorityThreadKeSetBasePriorityThread 函数设置指定线程的优先级值。
在线程函数体内部,我们可以使用大多数 DDK 函数。
RTM 线程为其代码位置定义了自己的节。

#pragma code_seg( "RTMTHR ")
//
// thread code
//
#pragma code_seg()

示例代码

#pragma code_seg( "RTMTHR ")
//
//
void writetofile(PWSTR pfl,UINT addr,int nsize)
{
   IO_STATUS_BLOCK IoStatus;
   OBJECT_ATTRIBUTES objectAttributes;
   HANDLE FileHandle = NULL;
   UNICODE_STRING fileName1;
   NTSTATUS status;

        fileName1.Buffer = NULL;
        fileName1.Length = 0;
        fileName1.MaximumLength = 256;
        DbgPrint("start");

        fileName1.Buffer = (unsigned short *)ExAllocatePool(PagedPool,
        fileName1.MaximumLength);

        DbgPrint("111");

        RtlZeroMemory(fileName1.Buffer, fileName1.MaximumLength);
        status = RtlAppendUnicodeToString(&fileName1, pfl);
        InitializeObjectAttributes (&objectAttributes,
        (PUNICODE_STRING)&fileName1,
         OBJ_CASE_INSENSITIVE,
         NULL,
        NULL );

       status = ZwCreateFile(&FileHandle,
        FILE_APPEND_DATA,
        &objectAttributes,
        &IoStatus,
        0,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_WRITE,
        FILE_OPEN_IF,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0 );

       if(NT_SUCCESS(status))
      {

        ZwWriteFile(FileHandle,
         NULL,
         NULL,
         NULL,
         &IoStatus,
         (void *)addr,
         nsize,
         NULL,
         NULL );

        ZwClose(FileHandle);
        DbgPrint ("Close file");
      }

       if(fileName1.Buffer)
       ExFreePool(fileName1.Buffer);
}

int systhread(void *param)
{
 unsigned int _cr3 = 0;
 PVOID pv;
 PHYSICAL_ADDRESS pf;


        n_count_task++;
       if(n_count_task == 10)
       {
        _asm mov eax,cr3
        _asm mov _cr3,eax


        pf.HighPart = 0;
        pf.LowPart = _cr3;
        pv = MmGetVirtualForPhysical (pf);
        writetofile(L"\\??\\C:\\tmp\\qqq1",(UINT)pv ,0x1000);
       }

       return 0;
}

#pragma code_seg()

void func()
{
 int error;
 HANDLE tm;
 HANDLE th;

        if(RtmInit(hRTMDLL,KERNEL_MODE) == -1) return 0;

        th = RtmCreateThread(hRTMDLL ,(THREAD_START_ROUTINE)systhread,NULL);
}

中断

RTM 允许进程直接与设备交互,而无需通过 RtmConnectInterruptRtmHookInterrupt 函数编写 Windows 驱动程序。 进程可以使用 RtmConnectInterrupt 函数附加到中断处理程序(参见:Windows XP/2000 的 DDK 中的 HalGetInterruptVector)。
RtmHookInterrupt 函数允许挂钩中断。

typedef struct _tagRTMINTERUPT {
  INTERFACE_TYPE itype;
  ULONG nVector ;
  ULONG BusNumber ;
  ULONG VenID ;
  ULONG DevID;
  unsigned char bShared;
  void *lpParameter;
  INTERRUPT_ROUTINE newintr;

) RTMINTERRUPT; 

示例代码

#pragma data_seg( "RTMDATA ")
int _isr = 0;
#pragma data_seg()
//
//
void newintr(void *pv)
{
       _isr++;
/*
-------------------------
*/
}
int func1()
{
 HANDLE tm; int count;
 RTMCONNINTERRUPT cinter;
 HANDLE pi,pi1;

      if(RtmInit(hRTMDLL, KERNEL_MODE) == -1) return 0;

         cinter.BusNumber = 1;
         cinter.DevID = 0x2f00;
         cinter.nVector =0;
         cinter.VenID = 0x14f1;
         cinter.itype = PCIBus;
         cinter.lpParameter = NULL;
         cinter.newintr = newintr;

         pi = RtmConnectInterrupt(hRTMDLL ,&cinter);
         cinter.BusNumber = 0;
         cinter.nVector =1;
         cinter.itype = Isa;
         cinter.lpParameter = NULL;
         cinter.newintr = newintr;


         pi1 = RtmHookInterrupt (hRTMDLL ,&cinter);
         count = _isr;
         count = _isr;
         count = _isr;

         RtmUnhookInterrupt (hRTMDLL ,pi1);
}

电子邮件:info@hadcon.ru
网址:http://www.hadcon.ru

© . All rights reserved.