遍历 USB devcie,读取设备描述符 device descriptor【转】
转自:http://blog.csdn.net/flyyyri/article/details/5480347
理论:
对于USB接口的设备,现在越来越多了。本篇我们就通过获取一个USB扫描仪设备中的序列号,来介绍如何获取usb设备的一些硬件信息。对于usb设备都是采用HCD0,HCD1,HCD2,HCD3等符号描述的。如下图:
因此,有了这个名字,我们就可以使用CreateFile来打开usb设备。然后使用DeviceIoControl函数与usb设备通讯了。HCD是host controller driver的简写。需要了解详情的,还要仔细的阅读usb协议。
usb的通讯基本步骤如下图所示:
基本步骤:
1)打开HCD%X
2) 得到上面的USB root hub
3) 遍历usb root hub上连接的usb 设备。获取信息
4)如果有多个usb口,循环前3步。
下面介绍通讯用的几个IOCTL:
1)USB_HCD_DRIVERKEY_NAME ,用于获取USB设备驱动在注册表中的键名。相应的一个结构体是:
typedef struct _USB_HCD_DRIVERKEY_NAME
{
ULONG ActualLength;
WCHAR DriverKeyName[1];
} USB_HCD_DRIVERKEY_NAME, *PUSB_HCD_DRIVERKEY_NAME;
2)IOCTL_USB_GET_ROOT_HUB_NAME,用于获取root hub 键名。使用的结构体,跟上面一样。
typedef struct _USB_ROOT_HUB_NAME
{
ULONG ActualLength;
WCHAR RootHubName[1];
} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;
3)IOCTL_USB_GET_NODE_INFORMATION,用于获取连接在root hub上的节点设备信息。也就是我们接在usb口上的所有usb设备的信息,对应的结构体:
typedef struct _USB_NODE_INFORMATION
{
USB_HUB_NODE NodeType;
union {
USB_HUB_INFORMATION HubInformation;
USB_MI_PARENT_INFORMATION MiParentInformation;
} u;
} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;
typedef struct _USB_MI_PARENT_INFORMATION
{
ULONG NumberOfInterfaces;
} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION;
typedef struct _USB_HUB_INFORMATION
{
USB_HUB_DESCRIPTOR HubDescriptor;
BOOLEAN HubIsBusPowered;
} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;
typedef struct _USB_HUB_DESCRIPTOR
{
UCHAR bDescriptorLength; // Length of this descriptor
UCHAR bDescriptorType; // Hub configuration type
UCHAR bNumberOfPorts; // number of ports on this hub
USHORT wHubCharacteristics; // Hub Charateristics
UCHAR bPowerOnToPowerGood; // port power on till power good in 2ms
UCHAR bHubControlCurrent; // max current in mA
//
// room for 255 ports power control and removable bitmask
UCHAR bRemoveAndPowerMask[64];
} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
4) IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, 用于获取接在usb口上的单个usb设备的信息,对应的结构体:
typedef struct _USB_NODE_CONNECTION_INFORMATION
{
ULONG ConnectionIndex;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UCHAR CurrentConfigurationValue;
BOOLEAN LowSpeed;
BOOLEAN DeviceIsHub;
USHORT DeviceAddress;
ULONG NumberOfOpenPipes;
USB_CONNECTION_STATUS ConnectionStatus;
USB_PIPE_INFO PipeList[0];
} USB_NODE_CONNECTION_INFORMATION, *PUSB_NODE_CONNECTION_INFORMATION;
4)IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, 用于获取usb设备的描述信息。
typedef struct _USB_DEVICE_DESCRIPTOR
{
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
typedef struct _USB_DEVICE_DESCRIPTOR
{
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
typedef enum _USB_CONNECTION_STATUS
{
NoDeviceConnected,
DeviceConnected,
/* failure codes, these map to fail reasons */
DeviceFailedEnumeration,
DeviceGeneralFailure,
DeviceCausedOvercurrent,
DeviceNotEnoughPower,
DeviceNotEnoughBandwidth,
DeviceHubNestedTooDeeply,
DeviceInLegacyHub
} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;
typedef struct _USB_PIPE_INFO
{
USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG ScheduleOffset;
} USB_PIPE_INFO, *PUSB_PIPE_INFO;
typedef struct _USB_ENDPOINT_DESCRIPTOR
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bEndpointAddress;
UCHAR bmAttributes;
USHORT wMaxPacketSize;
UCHAR bInterval;
} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
需要注意一点,如果要得到pid,vid,则直接从USB_DEVICE_DESCRIPTOR结构中取出idVendor,idProduct这两项的值就行了。如果要得到序列号,则不是取出 iSerialNumber就可以的。这里的 iSerialNumber仅仅是一个索引值。如果想得到序列号,就需要定义一个结构,然后给设备发送个请求。请求的结构如下图:
代码参照GetStringDescriptor函数。可以根据iSerialNumber偏移,取出其对应的字符串,存放在上图USB_STRING_DESCRIPTOR结构中。
#include "windows.h"
#include "PlkUsbIo.h"
#include <malloc.h>
#define NUM_HCS_TO_CHECK 10
/******************************************************************/
bool EnumUsbDevice();
PCHAR GetDriverKeyName(HANDLE Hub, ULONG ConnectionIndex);
PCHAR GetHCDDriverKeyName(HANDLE HCD);
PCHAR GetRootHubName(HANDLE HostController);
PCHAR WideStrToMultiStr(PWCHAR WideStr);
bool GetStringDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex,
UCHAR DescriptorIndex ,
CHAR * outBuff);
/******************************************************************/
int main(int argc, char* argv[])
{
EnumUsbDevice();
return 0;
}
bool EnumUsbDevice()
{
char HCName[16];
int HCNum;
HANDLE hHCDev;
PCHAR rootHubName;
ULONG index;
BOOL success;
PUSB_NODE_CONNECTION_INFORMATION connectionInfo;
HANDLE hHubDevice;
for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
{
wsprintf(HCName, "////.//HCD%d", HCNum);
hHCDev = CreateFile(HCName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hHCDev == INVALID_HANDLE_VALUE)
break;
PCHAR driverKeyName, deviceDesc;
driverKeyName = GetHCDDriverKeyName(hHCDev);
if(driverKeyName == NULL)
goto end;
ULONG nBytes;
rootHubName =(char*) GetRootHubName(hHCDev);
if(rootHubName==NULL)
goto end;
PUSB_NODE_INFORMATION HubInfo;
HubInfo = (PUSB_NODE_INFORMATION)malloc(sizeof(USB_NODE_INFORMATION));
PCHAR deviceName;
deviceName = (PCHAR)malloc(strlen(rootHubName) + sizeof("////.//"));
if (rootHubName != NULL)
{
strcpy(deviceName, "////.//");
strcpy(deviceName + sizeof("////.//") - 1, rootHubName);
hHubDevice = CreateFile(deviceName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
free(deviceName);
if (hHubDevice == INVALID_HANDLE_VALUE)
goto end;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_INFORMATION,
HubInfo,
sizeof(USB_NODE_INFORMATION),
HubInfo,
sizeof(USB_NODE_INFORMATION),
&nBytes,
NULL);
if (!success)
goto end;
}
int port;
port=HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts;
for (index=1; index <= port; index++)
{
ULONG nBytes;
nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
sizeof(USB_PIPE_INFO) * 30;
connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)malloc(nBytes);
if (connectionInfo == NULL)
goto end;
connectionInfo->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
connectionInfo,
nBytes,
connectionInfo,
nBytes,
&nBytes,
NULL);
if (!success)
{
free(connectionInfo);
goto end;
}
deviceDesc = NULL;
if (connectionInfo->ConnectionStatus != NoDeviceConnected)
{
driverKeyName = GetDriverKeyName(hHubDevice,
index);
if (driverKeyName)
{
free(driverKeyName);
}
}
if (connectionInfo->ConnectionStatus == DeviceConnected)
{
//取出序列号索引
UCHAR nSerialno = connectionInfo->DeviceDescriptor.iSerialNumber;
CHAR OutBuff[20] = {0};
GetStringDescriptor(hHubDevice,connectionInfo->ConnectionIndex,nSerialno,OutBuff);
//判断序列号是否有效
if(序列号是否有效)
{
CloseHandle(hHubDevice);
CloseHandle(hHCDev);
return true;
}
}
}
end:;
}
CloseHandle(hHubDevice);
CloseHandle(hHCDev);
return false;
}
PCHAR GetDriverKeyName(HANDLE Hub, ULONG ConnectionIndex)
{
BOOL success;
ULONG nBytes;
USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName;
PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW;
PCHAR driverKeyNameA;
driverKeyNameW = NULL;
driverKeyNameA = NULL;
driverKeyName.ConnectionIndex = ConnectionIndex;
success = DeviceIoControl(Hub,
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
&driverKeyName,
sizeof(driverKeyName),
&driverKeyName,
sizeof(driverKeyName),
&nBytes,
NULL);
if (!success)
{
goto GetDriverKeyNameError;
}
nBytes = driverKeyName.ActualLength;
if (nBytes <= sizeof(driverKeyName))
{
goto GetDriverKeyNameError;
}
driverKeyNameW = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)malloc(nBytes);
if (driverKeyNameW == NULL)
{
goto GetDriverKeyNameError;
}
driverKeyNameW->ConnectionIndex = ConnectionIndex;
success = DeviceIoControl(Hub,
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
driverKeyNameW,
nBytes,
driverKeyNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
goto GetDriverKeyNameError;
}
driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
free(driverKeyNameW);
return driverKeyNameA;
GetDriverKeyNameError:
if (driverKeyNameW != NULL)
{
free(driverKeyNameW);
driverKeyNameW = NULL;
}
return NULL;
}
PCHAR GetRootHubName(HANDLE HostController)
{
BOOL success;
ULONG nBytes;
USB_ROOT_HUB_NAME rootHubName;
PUSB_ROOT_HUB_NAME rootHubNameW;
PCHAR rootHubNameA;
rootHubNameW = NULL;
rootHubNameA = NULL;
success = DeviceIoControl(HostController,
IOCTL_USB_GET_ROOT_HUB_NAME,
0,
0,
&rootHubName,
sizeof(rootHubName),
&nBytes,
NULL);
if (!success)
{
goto GetRootHubNameError;
}
nBytes = rootHubName.ActualLength;
rootHubNameW =(PUSB_ROOT_HUB_NAME) malloc(nBytes);
if (rootHubNameW == NULL)
{
goto GetRootHubNameError;
}
success = DeviceIoControl(HostController,
IOCTL_USB_GET_ROOT_HUB_NAME,
NULL,
0,
rootHubNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
goto GetRootHubNameError;
}
rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName);
free(rootHubNameW);
return rootHubNameA;
GetRootHubNameError:
if (rootHubNameW != NULL)
{
free(rootHubNameW);
rootHubNameW = NULL;
}
return NULL;
}
PCHAR GetHCDDriverKeyName(HANDLE HCD)
{
BOOL success;
ULONG nBytes;
USB_HCD_DRIVERKEY_NAME driverKeyName;
PUSB_HCD_DRIVERKEY_NAME driverKeyNameW;
PCHAR driverKeyNameA;
driverKeyNameW = NULL;
driverKeyNameA = NULL;
success = DeviceIoControl(HCD,
IOCTL_GET_HCD_DRIVERKEY_NAME,
&driverKeyName,
sizeof(driverKeyName),
&driverKeyName,
sizeof(driverKeyName),
&nBytes,
NULL);
if (!success)
{
goto GetHCDDriverKeyNameError;
}
nBytes = driverKeyName.ActualLength;
if (nBytes <= sizeof(driverKeyName))
{
goto GetHCDDriverKeyNameError;
}
driverKeyNameW =(PUSB_HCD_DRIVERKEY_NAME) malloc(nBytes);
if (driverKeyNameW == NULL)
{
goto GetHCDDriverKeyNameError;
}
success = DeviceIoControl(HCD,
IOCTL_GET_HCD_DRIVERKEY_NAME,
driverKeyNameW,
nBytes,
driverKeyNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
goto GetHCDDriverKeyNameError;
}
driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
free(driverKeyNameW);
return driverKeyNameA;
GetHCDDriverKeyNameError:
if (driverKeyNameW != NULL)
{
free(driverKeyNameW);
driverKeyNameW = NULL;
}
return NULL;
}
PCHAR WideStrToMultiStr(PWCHAR WideStr)
{
ULONG nBytes;
PCHAR MultiStr;
nBytes = WideCharToMultiByte(
CP_ACP,
0,
WideStr,
-1,
NULL,
0,
NULL,
NULL);
if (nBytes == 0)
{
return NULL;
}
MultiStr =(PCHAR) malloc(nBytes);
if (MultiStr == NULL)
{
return NULL;
}
nBytes = WideCharToMultiByte(
CP_ACP,
0,
WideStr,
-1,
MultiStr,
nBytes,
NULL,
NULL);
if (nBytes == 0)
{
free(MultiStr);
return NULL;
}
return MultiStr;
}
bool GetStringDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex,
UCHAR DescriptorIndex ,
CHAR * outBuff
)
{
BOOL success;
ULONG nBytes;
ULONG nBytesReturned;
UCHAR stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + MAXIMUM_USB_STRING_LENGTH];
PUSB_DESCRIPTOR_REQUEST stringDescReq;
PUSB_STRING_DESCRIPTOR stringDesc;
nBytes = sizeof(stringDescReqBuf);
stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf;
stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1);
::ZeroMemory(stringDescReq,nBytes);
stringDescReq->ConnectionIndex = ConnectionIndex;
stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex;
stringDescReq->SetupPacket.wIndex = GetSystemDefaultLangID();
stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
success = DeviceIoControl(hHubDevice,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
stringDescReq,nBytes,
stringDescReq,nBytes,
&nBytesReturned,NULL);
if (!success || nBytesReturned < 2)
return false;
if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE)
return false;
if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST))
return false;
if (stringDesc->bLength % 2 != 0)
return false;
WCHAR * wChar = new WCHAR[stringDesc->bLength + 1];
memcpy(wChar,stringDesc->bString,stringDesc->bLength);
char *szTemp = WideStrToMultiStr(wChar);
lstrcpy(outBuff, szTemp);
if(szTemp)
delete []szTemp;
if(wChar)
delete []wChar;
return true;
}
分析:
1)首先假定有10个usb接口
#define NUM_HCS_TO_CHECK 10
2)循环打开这10个usb端口,如果端口没有这么多,调用CreateFile,就会返回 INVALID_HANDLE_VALUE。
for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
{
wsprintf(HCName, "////.//HCD%d", HCNum);
hHCDev = CreateFile(HCName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hHCDev == INVALID_HANDLE_VALUE)
break;
3)获取root hub
ULONG nBytes;
rootHubName =(char*) GetRootHubName(hHCDev);
if(rootHubName==NULL)
goto end;
4) 遍历连接在root hub上的节点
int port;
port=HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts;
for (index=1; index <= port; index++)
{
ULONG nBytes;
nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
sizeof(USB_PIPE_INFO) * 30;
connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)malloc(nBytes);
if (connectionInfo == NULL)
goto end;
connectionInfo->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
connectionInfo,
nBytes,
connectionInfo,
nBytes,
&nBytes,
NULL);
if (!success)
{
free(connectionInfo);
goto end;
}
5)根据节点的连接状态,获取节点信息,得到序列号。
if (connectionInfo->ConnectionStatus == DeviceConnected)
{
//取出序列号索引
UCHAR nSerialno = connectionInfo->DeviceDescriptor.iSerialNumber;
CHAR OutBuff[20] = {0};
GetStringDescriptor(hHubDevice,connectionInfo->ConnectionIndex,nSerialno,OutBuff);
6)得到序列号的方法在理论部分已经详细说明了,对应的函数是GetStringDescriptor,这里不再重复。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jtujtujtu/archive/2009/11/19/4836900.aspx
遍历 USB devcie,读取设备描述符 device descriptor【转】的更多相关文章
- usb协议分析-设备描述符配置包-描述符
/* usb协议分析仅供大家参考---设备描述符配置包,设备描述符, 地址设置, 配置描述符, 字符串描述符 */ /* -1- usb设备描述符配置包 */ typedef struct _USB_ ...
- USB系列之二:读取USB设备的描述符
在前面的文章中,我们已经给出了USB协议的链接地址,从这篇文章起,我们会涉及到许多USB 1.1的内容,我们的指导思想是先从熟悉USB 1.1协议入手,先使用现成的HCD和USBD,直接面对客户端驱动 ...
- Win10 设备管理器一个USB设备描述符请求失败解决方法
问题:进入设备管理器,发现[通用串行总线控制器]下有一项带有黄色[!]未知USB设备(设备描述符请求失败). 或者 解决方法如下: 1.点击Windows键 +R或者(点击系统桌面左下角[开始],在开 ...
- Qt下libusb-win32的使用(一)打印设备描述符
主要是在前一篇的基础上,学习libusb-win32的API使用.程序很简单,就是打印指定USB设备的设备描述符(当然其他描述符也是可以的). #include "testlibusb.h& ...
- usb驱动开发9之设备描述符
前面分析了usb的四大描述符之端点描述符,接口描述符(每一个接口对应一个功能,与之配备相应驱动),配置描述符,最后分析设备如何包括这些描述符.首先记住,在usb的世界里,设备大于配置,配置大于接口,接 ...
- USB设备描述符
/* USB Standard Device Descriptor */ const u8 Virtual_Com_Port_DeviceDescriptor[] = { 0x12, /* bLeng ...
- STM32 USB设备描述符、配置描述符、端点描述符含义
查了一整天的资料,自己把不懂的全部试了一遍 一下是程序以及注释 /* USB设备描述符*/ const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ ...
- qq2440启动linux后插入u盘出现usb 1-1: device descriptor read/64, error -110,usb 1-1: device not accepting address 8, error -110
上位机:ubuntu14.04 64bit 下位机:qq2440 交叉编译器:arm-linux-gcc 3.4.1 下位机使用的linux内核版本:kernel2.6.13 1.插入u盘时错误信息如 ...
- USB设备描述符和请求命令
USB设备描述符和请求命令 介绍标准的USB设备描述符和请求命令. 标准的USB描述符 当USB设备第一次连接到主机上时,要接收主机的枚举和配置,目的就是让主机知道该设备具有什么功能.是哪一类的USB ...
随机推荐
- NOIP赛前集训营-提高组(第一场)#B 数数字
题目描述 小N对于数字的大小一直都有两种看法.第一种看法是,使用字典序的大小(也就是我们常用的判断数字大小的方法,假如比较的数字长度不同,则在较短一个前面补齐前导0,再比较字典序),比如43<3 ...
- winrar 授权破解过期解决
RAR registration data Federal Agency for Education 1000000 PC usage license UID=b621cca9a84bc5deffbf ...
- 51nod 1564 区间的价值 | 分治 尺取法
51nod 1564 区间的价值 题面 一个区间的价值是区间最大值×区间最小值.给出一个序列\(a\), 求出其中所有长度为k的子区间的最大价值.对于\(k = 1, 2, ..., n\)输出答案. ...
- 洛谷 P3698 [CQOI2017]小Q的棋盘 解题报告
P3698 [CQOI2017]小Q的棋盘 题目描述 小 Q 正在设计一种棋类游戏. 在小 Q 设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能在有连线的格点之间移动.整个棋盘上 ...
- bug -- android 7.0 popwindow显示位置异常情况解决
android 7.0 popwindow显示位置异常,在android7.1官方进行解决了,但是还是要多7.0的bug进行解决,我的解决方案里面通过重写popwindow进行适配: import a ...
- python之旅:并发编程之多进程理论部分
一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行): egon在一个时间段内有很多任务要做:python备课的任务,写书的任 ...
- Codeforces Round #426 (Div. 2) D 线段树优化dp
D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...
- c动态分配结构体二维数组
这个问题我纠结了蛮久了,因为前面一直忙(自己也懒了点),所以没有能好好研究这个.希望这篇文章能够帮助你们. #include <stdio.h> #include <stdlib.h ...
- timeshift 安装使用说明
https://blog.csdn.net/hunter___/article/details/79751379 这里介绍一个可视化的备份软件:Timeshift,它不只能备份你的个人文件夹或应用程序 ...
- P2054 [AHOI2005]洗牌
P2054 [AHOI2005]洗牌 题目描述 为了表彰小联为Samuel星球的探险所做出的贡献,小联被邀请参加Samuel星球近距离载人探险活动. 由于Samuel星球相当遥远,科学家们要在飞船中度 ...