34、I/O端口操作

简介:     I/O端口操作在Windows操作系统中属于特权命令,必须在内核模式下运行。在DOS中,I/O端口操作主要通过IN/OUT指令来进行。  一、I/O端口操作实现  1、DDK实现I/O端口操作 READ_PORT_UCHAR The READ_PORT_UCHAR macro reads a byte from the specified port address。

    I/O端口操作在Windows操作系统中属于特权命令,必须在内核模式下运行。在DOS中,I/O端口操作主要通过IN/OUT指令来进行。 

一、I/O端口操作实现 

1DDK实现I/O端口操作

READ_PORT_UCHAR

The READ_PORT_UCHAR macro reads a byte from the specified port address

http://msdn.microsoft.com/en-us/library/ff560797%28VS.85%29.aspx

2、工具软件WinIO

第三方库。5个文件。

WinIO.dll 封装了驱动程序调用函数。

WinIO.lib 用来与应用程序链接编译。

WinIO.h 提供了封装函数的声明。

使用时必须把WinIO.sys和应用程序放在同一个目录。

WinIO.VXD9598等相关。 

代码
 
   
#include < Windows.h >
#include
< stdio.h >

#include
" .\winiolib\WinIo.h "

int main()
{
// 打开WinIO驱动
bool bRet = InitializeWinIo();
if (bRet)
{
printf(
" Load Dirver successfully!\n " );

// 对0x378端口进行输出操作,8位操作
SetPortVal( 0x378 , 0 , 1 );

// 关闭WinIO驱动
ShutdownWinIo();
}


return 0 ;
}

示例代码 P391

3、端口操作实现

法一:利用DDK提供的6个端口操作函数

 

代码
 
   
// IOCTLS.H -- IOCTL code definitions for fileio driver
// Copyright (C) 1999 by Walter Oney
// All rights reserved

#ifndef IOCTLS_H
#define IOCTLS_H

#ifndef CTL_CODE
#pragma message("CTL_CODE undefined. Include winioctl.h or wdm.h")
#endif

#define READ_PORT CTL_CODE(\
FILE_DEVICE_UNKNOWN, \
0x800 , \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)

#define WRITE_PORT CTL_CODE(\
FILE_DEVICE_UNKNOWN, \
0x801 , \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)


#endif

// .h
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName;
// 设备名称
UNICODE_STRING ustrSymLinkName; // 符号链接名

PUCHAR buffer;
// 缓冲区
ULONG file_length; // 模拟的文件长度,必须小于MAX_FILE_LENGTH
} DEVICE_EXTENSION, * PDEVICE_EXTENSION;

// function.cpp
#include < windows.h >
#include
< stdio.h >

#include
" function.h "

// DWORD ReadPort(HANDLE hDevice,DWORD port)
// {
// DWORD dwOutput;
// DWORD dwRead;
// DeviceIoControl(hDevice, IOCTL_READ_PORT_ULONG, &port, 4, &dwOutput, 4, &dwRead, NULL);
// return dwOutput;
// }
// VOID WritePort(HANDLE hDevice,DWORD port,DWORD value)
// {
// PVOID buffer[2];
// buffer[0] = (PVOID)port;
// buffer[1] = (PVOID)value;
// DWORD dwWrite;
// DeviceIoControl(hDevice, IOCTL_WRITE_PORT_ULONG, &port, 8, NULL, 0, &dwWrite, NULL);
// }
// VOID TestDriver(HANDLE hDevice)
// {
// DWORD dwOutput;
// DeviceIoControl(hDevice, IOCTL_TEST, NULL, 0, NULL, 0, &dwOutput, NULL);
// }

// driver.cpp
#pragma PAGEDCODE
NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
NTSTATUS status
= STATUS_SUCCESS;
KdPrint((
" Enter HelloDDKDeviceIOControl\n " ));

// 得到当前堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
// 得到输入缓冲区大小
ULONG cbin = stack -> Parameters.DeviceIoControl.InputBufferLength;
// 得到输出缓冲区大小
ULONG cbout = stack -> Parameters.DeviceIoControl.OutputBufferLength;
// 得到IOCTL码
ULONG code = stack -> Parameters.DeviceIoControl.IoControlCode;

ULONG info
= 0 ;

switch (code)
{
// process request
case READ_PORT:
{
KdPrint((
" READ_PORT\n " ));
// 缓冲区方式IOCTL
// 显示输入缓冲区数据
PULONG InputBuffer = (PULONG)pIrp -> AssociatedIrp.SystemBuffer;
ULONG port
= (ULONG)( * InputBuffer);
InputBuffer
++ ;
UCHAR method
= (UCHAR)( * InputBuffer);

// 操作输出缓冲区
PULONG OutputBuffer = (PULONG)pIrp -> AssociatedIrp.SystemBuffer;

if (method == 1 ) // 8位操作
{
* OutputBuffer = READ_PORT_UCHAR((PUCHAR)port);
}
else if (method == 2 ) // 16位操作
{
* OutputBuffer = READ_PORT_USHORT((PUSHORT)port);
}
else if (method == 4 ) // 32位操作
{
* OutputBuffer = READ_PORT_ULONG((PULONG)port);
}

// 设置实际操作输出缓冲区长度
info = 4 ;

break ;
}
case WRITE_PORT:
{
KdPrint((
" WRITE_PORT\n " ));
// 缓冲区方式IOCTL
// 显示输入缓冲区数据
PULONG InputBuffer = (PULONG)pIrp -> AssociatedIrp.SystemBuffer;
ULONG port
= (ULONG)( * InputBuffer);
InputBuffer
++ ;
UCHAR method
= (UCHAR)( * InputBuffer);
InputBuffer
++ ;
ULONG value
= (ULONG)( * InputBuffer);

// 操作输出缓冲区
PULONG OutputBuffer = (PULONG)pIrp -> AssociatedIrp.SystemBuffer;

if (method == 1 ) // 8位操作
{
WRITE_PORT_UCHAR((PUCHAR)port,(UCHAR)value);
}
else if (method == 2 ) // 16位操作
{
WRITE_PORT_USHORT((PUSHORT)port,(USHORT)value);
}
else if (method == 4 ) // 32位操作
{
WRITE_PORT_ULONG((PULONG)port,(ULONG)value);
}

// 设置实际操作输出缓冲区长度
info = 0 ;
break ;
}


default :
status
= STATUS_INVALID_VARIANT;
}

// 完成IRP
pIrp -> IoStatus.Status = status;
pIrp
-> IoStatus.Information = info; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );

KdPrint((
" Leave HelloDDKDeviceIOControl\n " ));

return status;
}

// main.cpp
#include < windows.h >
#include
< stdio.h >
// 使用CTL_CODE必须加入winioctl.h
#include < winioctl.h >
#include
" ..\NT_Driver\Ioctls.h "

int main()
{
HANDLE hDevice
=
CreateFile(
" \\\\.\\HelloDDK " ,
GENERIC_READ
| GENERIC_WRITE,
0 , // share mode none
NULL, // no security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
// no template

if (hDevice == INVALID_HANDLE_VALUE)
{
printf(
" Failed to obtain file handle to device: "
" %s with Win32 error code: %d\n " ,
" MyWDMDevice " , GetLastError() );
return 1 ;
}

DWORD dwOutput ;
DWORD inputBuffer[
3 ] =
{
0x378 , // 对0x378进行操作
1 , // 1代表8位操作,2代表16位操作,4代表32位操作
0 // 输出字节0
};

// 类似于Out_8((PUCHAR)0x378,0);
DeviceIoControl(hDevice, WRITE_PORT, inputBuffer, sizeof (inputBuffer), NULL, 0 , & dwOutput, NULL);

CloseHandle(hDevice);

return 0 ;
}

示例代码 P394

[1] 中还提供了一些其它方法

提升用户模式的方法是将应用程序的一个函数指针传递给驱动程序,在驱动程序接收到这个函数指针后,在内核模式下执行此函数。

I/O 允许位图设置可以让不具备足够权限的程序存取I/O端口。I/O允许位图设置是利用一个位代表每个I/O地址。

每个PC系统至少包含一个8253可编程时钟或等价芯片,这个时钟包含三个独立的16位时钟。时钟0用于基本系统时钟,时钟1用于PC系统上的DRAM刷新,时钟2用于一般的应用程序,如扬声器音调控制。

并口设备的操作

操作PC上的并口设备,主要也是设置和读取并口设备对应的I/O端口。数据、状态、控制寄存器。进一步的介绍可以参见[1]

参考:

[1] Windows 驱动程序开发技术详解,张帆

 

目录
相关文章
|
Web App开发 存储
Python+selenium 自动化-操作已启用的chrome浏览器实例演示,chrome启用调试端口方法
Python+selenium 自动化-操作已启用的chrome浏览器实例演示,chrome启用调试端口方法
577 0
Python+selenium 自动化-操作已启用的chrome浏览器实例演示,chrome启用调试端口方法
|
3月前
|
编译器 API C语言
C语言与硬件交互:通过I/O端口控制硬件。
C语言与硬件交互:通过I/O端口控制硬件。
90 0
|
5月前
|
Oracle 关系型数据库 MySQL
实时计算 Flink版操作报错合集之ip和端口都是通的,连接池设置为200,连接报错,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
Zp
|
网络协议 Linux
Linux系统查看端口的操作办法
Linux系统查看端口的操作办法
Zp
608 0
msp430 I/O端口中断实验
单片机的P1.0引脚连接一个LED灯, P1.1引脚连接一个开关。要求 编写程序,利用中断方法检测P1.1引脚处的开关是否被按下。每按一下开关,P1.0连接的LED 亮灭状态就变换一次。
139 0
msp430 I/O端口中断实验
|
网络协议 Linux 网络安全
CentOS7在防火墙开启与关闭以及端口操作
CentOS7在防火墙开启与关闭以及端口操作
407 0
CentOS7在防火墙开启与关闭以及端口操作
|
安全 网络协议 Linux
CentOS: 开放80、22、3306等端口操作
#/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT #/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT #/sbin/iptables -I INPUT -p tcp --dport 33
7284 1
|
消息中间件 API Windows
交换机发现邻居操作,查看端口和ip
版权声明:转载请注明出处:http://blog.csdn.net/dajitui2024 https://blog.csdn.net/dajitui2024/article/details/79396249 类似思科CDP的能看见邻居交换机。
1538 0