如何在linux和windows下获得硬盘设备的接口通道信息

       原创文章,转载请注明出处,谢谢!       
       作者:清林,博客名:飞空静渡

 

首先,在linux下,要获得硬盘的接口通道信息,我们可以运行:cat /proc/scsi/scsi,我机子的输出如下:

 

Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: ATA      Model: MAXTOR STM325031 Rev: 3.AA
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi0 Channel: 00 Id: 01 Lun: 00
  Vendor: ATA      Model: WDC WD1600JS-58N Rev: 10.0
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi2 Channel: 00 Id: 00 Lun: 00
  Vendor: Toshiba  Model: External USB HDD Rev: 1.02
  Type:   Direct-Access                    ANSI  SCSI revision: 02
Host: scsi20 Channel: 00 Id: 00 Lun: 00
  Vendor: TOSHIBA  Model: MK1652GSX        Rev: LV01
  Type:   Direct-Access                    ANSI  SCSI revision: 00

 

这就是这几个硬盘设备在各个通道上的信息。

 

如果是在Win7下(winXP看不到Channel和Lun等信息),我们可以右击“我的电脑”--“管理”--“硬盘管理”--选择一个硬盘(不是分区)右击--“属性”,然后就可以看到了,下面是一个硬盘属性的截图:

 

我们对比linux和windows下的这个信息(Channel 0, Target 0, Lun 0),这个信息就是我们硬盘上的一下接口的信息。

现在的问题是我们如何来获取这个信息呢,就是写个程序来获取这个信息。

 

首先,先看下linux,当我 cat /proc/scsi/scsi 输出的信息如上面所示,我只查看第4个硬盘的信息,如下:


Host: scsi20 Channel: 00 Id: 00 Lun: 00
  Vendor: TOSHIBA  Model: MK1652GSX        Rev: LV01
  Type:   Direct-Access                    ANSI  SCSI revision: 00

 

再集中选取一下:

scsi20 Channel: 00 Id: 00 Lun: 00

这几个接口的信息就是:

20 00 00 00

 

这几个信息,我们又怎么样获得呢,答案就是udev,下面我运行这个命令:

udevadmin monitor

运行这个命令时,udev会等待一个硬盘的插拔事件,这时我把我的第四个硬盘(也是个外置的移动硬盘)拔掉,这样就得到一个硬盘从系统上移出的信息,udev就可以获得,我的输出如下:

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[1269851734.642182] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/scsi_generic/sg3 (scsi_generic)
UDEV  [1269851734.642219] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/scsi_disk/20:0:0:0 (scsi_disk)
KERNEL[1269851734.642245] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/scsi_device/20:0:0:0 (scsi_device)
KERNEL[1269851734.642267] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/scsi_disk/20:0:0:0 (scsi_disk)
KERNEL[1269851734.642295] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/block/sdd/sdd2 (block)
KERNEL[1269851734.642321] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/block/sdd/sdd1 (block)
KERNEL[1269851734.642343] remove   /devices/virtual/bdi/8:48 (bdi)
KERNEL[1269851734.642368] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/block/sdd (block)
KERNEL[1269851734.642393] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0 (scsi)
KERNEL[1269851734.642416] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0 (scsi)
KERNEL[1269851734.642438] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/scsi_host/host20 (scsi_host)
KERNEL[1269851734.642460] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20 (scsi)
UDEV  [1269851734.643850] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/scsi_generic/sg3 (scsi_generic)
UDEV  [1269851734.643881] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/scsi_device/20:0:0:0 (scsi_device)
UDEV  [1269851734.644394] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/block/sdd/sdd2 (block)
UDEV  [1269851734.644426] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/scsi_host/host20 (scsi_host)
KERNEL[1269851734.644454] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0 (usb)
UDEV  [1269851734.644520] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/block/sdd/sdd1 (block)
KERNEL[1269851734.644625] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7 (usb)
UDEV  [1269851734.664949] remove   /devices/virtual/bdi/8:48 (bdi)
UDEV  [1269851734.665017] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0/block/sdd (block)
UDEV  [1269851734.665046] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0 (scsi)
UDEV  [1269851734.665069] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0 (scsi)
UDEV  [1269851734.665092] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20 (scsi)
UDEV  [1269851734.665118] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0 (usb)
UDEV  [1269851734.665162] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7 (usb)

 

好,我又集中的选取其中一条信息,如下:

KERNEL[1269851734.642182] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-7/1-7:1.0/host20/target20:0:0/20:0:0:0 /scsi_generic/sg3 (scsi_generic)

看下上面这条信息,我加红了其中的4个字段,它们就是20:0:0:0

这个字段的信息就是对应于 cat /proc/scsi/scsi输出的

scsi20 Channel: 00 Id: 00 Lun: 00

20 00 00 00

信息。

 

那在linux下个程序来获得这几个接口信息就简单了,具体可以看udev的源码或是看我的udev的序列文章《udev(九)-- 写个程序检测我们的设备插拔》及其前面的文章。

 

下面重点来看下Windows下如何得到,下面的代码是我写的代码中节选出来的,它可以打印出上图中的Location:后面的信息:

#include #include #include using namespace std; #define SECTOR_SIZE 512 void GetChannelInfo(std::vector &vids) { HDEVINFO hDevInfo; GUID guid = DiskClassGuid; BYTE buffer[SECTOR_SIZE]; DWORD dwRequiredSize ; TCHAR buf[SECTOR_SIZE]; DEVINST devInstParent; DWORD dwIndex; int nLength; SP_DEVICE_INTERFACE_DATA devInterfaceData; SP_DEVINFO_DATA devInfoData; PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail; hDevInfo = SetupDiGetClassDevs(&guid, NULL, NULL,DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if(hDevInfo == INVALID_HANDLE_VALUE) { return; } for(dwIndex = 0; ;dwIndex ++) { memset(&devInterfaceData, 0, sizeof(devInterfaceData)); devInterfaceData.cbSize = sizeof(devInterfaceData); // Get device Interface data. if(!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guid, dwIndex,&devInterfaceData)) { break; } memset(&devInfoData, 0, sizeof(devInfoData)); devInfoData.cbSize = sizeof(devInfoData); pDevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer; pDevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Get device interface detail data to get // Device Instance from SP_DEVINFO_DATA and // Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, pDevDetail, SECTOR_SIZE, &dwRequiredSize, &devInfoData); nLength = _tcslen(pDevDetail->DevicePath); HANDLE hDrive = CreateFile(pDevDetail->DevicePath,0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if ( hDrive != INVALID_HANDLE_VALUE ) { STORAGE_DEVICE_NUMBER sdn; DWORD dwBytesReturned = 0; DWORD dwStatus; dwStatus = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL); if ( dwStatus ) { _TCHAR PropertyBuffer[MAX_PATH] = {0}; DWORD dwRequest=1000; DWORD dwType=REG_SZ; memset(PropertyBuffer,0,sizeof(PropertyBuffer)); if (SetupDiGetDeviceRegistryProperty( hDevInfo,&devInfoData,SPDRP_LOCATION_INFORMATION ,NULL,(LPBYTE)PropertyBuffer,sizeof(PropertyBuffer),&dwRequest)) { wcout<

 

在vc下编译,你可以链接这两个库setupapi.lib,Rpcrt4.lib。

 

我在Win7下的输出是这样的:

Location: 0, Target 0, Lun 0

 

这里的关键是使用SetupDiGetDeviceRegistryProperty的SPDRP_LOCATION_INFORMATION参数来获取这个Location信息。

其实这个函数还可以获取设备的更多的信息,这些信息你可以在上图的Details的选项上,下面有个下拉菜单,每选一个下拉菜单中的选项都会在下面的TextEditor中显示相应的信息,而这些信息,我们就可以通过SetupDiGetDeviceRegistryProperty函数的第三个参数来获取,这些参数有:

 

#define SPDRP_DEVICEDESC                  (0x00000000)  // DeviceDesc (R/W)
#define SPDRP_HARDWAREID                  (0x00000001)  // HardwareID (R/W)
#define SPDRP_COMPATIBLEIDS               (0x00000002)  // CompatibleIDs (R/W)
#define SPDRP_UNUSED0                     (0x00000003)  // unused
#define SPDRP_SERVICE                     (0x00000004)  // Service (R/W)
#define SPDRP_UNUSED1                     (0x00000005)  // unused
#define SPDRP_UNUSED2                     (0x00000006)  // unused
#define SPDRP_CLASS                       (0x00000007)  // Class (R--tied to ClassGUID)
#define SPDRP_CLASSGUID                   (0x00000008)  // ClassGUID (R/W)
#define SPDRP_DRIVER                      (0x00000009)  // Driver (R/W)
#define SPDRP_CONFIGFLAGS                 (0x0000000A)  // ConfigFlags (R/W)
#define SPDRP_MFG                         (0x0000000B)  // Mfg (R/W)
#define SPDRP_FRIENDLYNAME                (0x0000000C)  // FriendlyName (R/W)
#define SPDRP_LOCATION_INFORMATION        (0x0000000D)  // LocationInformation (R/W)
#define SPDRP_PHYSICAL_DEVICE_OBJECT_NAME (0x0000000E)  // PhysicalDeviceObjectName (R)
#define SPDRP_CAPABILITIES                (0x0000000F)  // Capabilities (R)
#define SPDRP_UI_NUMBER                   (0x00000010)  // UiNumber (R)
#define SPDRP_UPPERFILTERS                (0x00000011)  // UpperFilters (R/W)
#define SPDRP_LOWERFILTERS                (0x00000012)  // LowerFilters (R/W)
#define SPDRP_BUSTYPEGUID                 (0x00000013)  // BusTypeGUID (R)
#define SPDRP_LEGACYBUSTYPE               (0x00000014)  // LegacyBusType (R)
#define SPDRP_BUSNUMBER                   (0x00000015)  // BusNumber (R)
#define SPDRP_ENUMERATOR_NAME             (0x00000016)  // Enumerator Name (R)
#define SPDRP_SECURITY                    (0x00000017)  // Security (R/W, binary form)
#define SPDRP_SECURITY_SDS                (0x00000018)  // Security (W, SDS form)
#define SPDRP_DEVTYPE                     (0x00000019)  // Device Type (R/W)
#define SPDRP_EXCLUSIVE                   (0x0000001A)  // Device is exclusive-access (R/W)
#define SPDRP_CHARACTERISTICS             (0x0000001B)  // Device Characteristics (R/W)
#define SPDRP_ADDRESS                     (0x0000001C)  // Device Address (R)
#define SPDRP_UI_NUMBER_DESC_FORMAT       (0X0000001D)  // UiNumberDescFormat (R/W)
#define SPDRP_DEVICE_POWER_DATA           (0x0000001E)  // Device Power Data (R)
#define SPDRP_REMOVAL_POLICY              (0x0000001F)  // Removal Policy (R)
#define SPDRP_REMOVAL_POLICY_HW_DEFAULT   (0x00000020)  // Hardware Removal Policy (R)
#define SPDRP_REMOVAL_POLICY_OVERRIDE     (0x00000021)  // Removal Policy Override (RW)
#define SPDRP_INSTALL_STATE               (0x00000022)  // Device Install State (R)
#define SPDRP_LOCATION_PATHS              (0x00000023)  // Device Location Paths (R)

#define SPDRP_MAXIMUM_PROPERTY            (0x00000024)  // Upper bound on ordinals

 

看下,里面或许有你想要的设备的某些信息 :)

 

其实SetupDiGetDeviceRegistryProperty函数是用于取代早前的CM_Get_DevNode_Registry_Property_Ex函数,而这个函数也可以获得设备的相关信息,例如,上面的Location信息,可以设置CM_Get_DevNode_Registry_Property_Ex函数的第二个参数设置成CM_DRP_LOCATION_INFORMATION,这样也可以获取设备的Location信息,其信息和SetupDiGetDeviceRegistryProperty函数的SPDRP_LOCATION_INFORMATION参数获取的是一样的。

 

你可能感兴趣的:(linux,WINDOWS)