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






3.14/5 (25投票s)
本文介绍了 Hadcon 针对 Windows 7/XP 的实时模块
引言
由于各种商业和技术原因,Microsoft Windows Vista、XP/2000 操作系统越来越多地被认为是部署实时系统的平台。原因包括:
- 该平台上有许多可用的应用程序
- 该平台上有多种可用的开发工具
- Microsoft Win32 应用程序编程接口 (API) 的丰富性
- 大量开发人员、支持人员和最终用户熟悉该系统
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_seg
、code_seg
和 bss_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
)。
您可以使用 KeSetPriorityThread
和 KeSetBasePriorityThread
函数设置指定线程的优先级值。
在线程函数体内部,我们可以使用大多数 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 允许进程直接与设备交互,而无需通过 RtmConnectInterrupt
或 RtmHookInterrupt
函数编写 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);
}