精华内容
下载资源
问答
  • Windows异步IO

    千次阅读 2014-07-17 08:50:05
    同步IO时,发出IO请求的线程会被挂起。而异步IO时发出请求的线程不会被挂起,而是可以继续执行。异步IO请求传给了设备驱动程序,被加入到驱动程序的请求队列中,驱动程序负责实际的IO操作。当设备驱动程序完成了对...

    1、异步IO说明

    同步IO时,发出IO请求的线程会被挂起。而异步IO时发出请求的线程不会被挂起,而是可以继续执行。异步IO请求传给了设备驱动程序,被加入到驱动程序的请求队列中,驱动程序负责实际的IO操作。当设备驱动程序完成了对队列中IO请求的处理,无论成功与否都必须通知应用程序。

    为了以异步的方式来访问设备,在调用CreateFile()时,必须传给dwFlagsAndAttributes参数FILE_FLAG_OVERLAPPED标志,这个标志告诉系统我们想要以异步的方式来访问设备;ReadFile()和WriteFile() 的pdwNumBytes参数可以传NULL,因为函数会立即返回,检查pdwNumBytes是没有意义的;ReadFile()和WriteFile()的pOverlapped参数必须传入一个已初始化的OVERLAPPED结构,其中Offset、OffsetHigh、hEvent必须在调用ReadFile()和WriteFile()前初始化,InternalInternalHigh由驱动程序设置。

    typedef struct _OVERLAPPED  
    {  
       DWORD Internal;     //错误代码。  
       DWORD InternalHigh; //已传输字节数。   
       DWORD Offset;       //低32位文件偏移。   
       DWORD OffsetHigh;   //高32位文件偏移。  
       HANDLE hEvent;      //事件对象句柄。   
    }OVERLAPPED,*LPOVERLAPPED;
    Internal:用来保存已处理的IO请求的错误码。一旦我们发出一个异步IO请求,设备驱动程序会立即将Internal设为STATUS_PENDING,表示没有错误。通过检查此值我们可以使用HasOverlappedIoCompeleted宏检查异步IO请求是否已经完成。该宏定义为#define HasOverlappedIoCompeleted(pOverlapped)\  
                                       ((pOverlapped)->Internal!=STATUS_PENDING) 

    InternalHigh:保存已传输的字节数。

    OffsetOffsetHigh:OffsetOffsetHigh共同构成一个64位的偏移量。它表示在访问文件时应该从何处访问设备。非文件设备必须为这两个成员都指定为0,否则IO请求将会失败。GetLastError返回ERROR_INVALID_PARAMETER

               之所以会在此处提供偏移量是因为:在执行异步操作时系统会忽略文件指针。如果不再此处指定,那么系统将无法知道下次应该从哪里开始读取数据。为了防止在同一个对象上进行多个异步调用时出现混淆,所有的异步调用IO请求都必须在OVERLAPPED结构中指定起始偏移量。

    hEvent:标识一个事件内核对象句柄。用来接收IO完成通知的4种方法(后面会有介绍)的最后一种:使用IO完成端口会使用到这个成员。

    2、异步IO注意事项

    一:设备驱动程序队列的异步设备IO请求不一定是以先入先出方式处理的。后被加入的请求也有可能先执行。

    二:如果请求的IO操作是以同步方式执行的,那么ReadFileWriteFile会返回非零值。如果请求的IO操作是以异步方式执行的或者在调用函数时出现错误,函数会返回false。必须调用GetLastError来检查到底发生了什么事。如果GetLastError 返回ERROR_IO_PENDING,那么IO请求已经被就加入到了队列。其他值则说明IO请求没有被加入到驱动程序队列中。此时GetLastError会返回一下几个错误码:ERROR_INVALID_USER_BUFFERERROR_NOT_ENOUGH_MEMORY.这两个错误码表示驱动程序请求队列已满,无法添加。

    三:我们以异步IO方式将IO请求添加到驱动程序队列中时,驱动程序会选择以同步的方式来处理请求。当我们从文件中读取数据时,系统会检查我们想要的数据是否在系统缓存中。如果数据已经在缓存中,系统就不会将我们的异步IO请求添加到设备驱动程序队列中。

    四:在异步IO请求完成之前,一定不能移动或是销毁发出IO请求所使用的数据缓存和OVERLAPPED数据。由于传给CreateFileWriteFile的是OVERLAPPED结构的地址,当系统将IO请求加入设备驱动程序会将地址传给驱动程序,否则将会导致内存访问违规。如以下代码中, 由于OVERLAPPEDbuff是从栈中分配的,函数执行完毕栈被平衡,但异步IO请求可能还未执行完毕。此时再访问栈空间很容易导致访问违规。为避免这种情况的可以从堆中分配内存。

        VOID ReadData(HANDLE hFile)     
        {  
           OVERLAPPED o={0};     
           BYTE buff[100];  
           ReadFile(hFile,buff,100,NULL,&o);  
        }  

    3、取消IO请求

    有时候我们想要在设备驱动程序对一个已经加入加入队列的设备IO请求进行处理之前将其取消,Windows为我们提供了多种方式:

    一:调用CancelIo()。该函数取消该文件句柄的所有等待的I/O操作。也可以关闭设备句柄,来取消所有已经添 加到队列中的所有IO请求。
       BOOL CancelIo(HANDLE hFile); 

    二:线程终止时,系统会自动取消该线程发出的所有IO请求。但如果请求的句柄具有与之相关联的IO完成端口,那么不在被取消之列。

    三:CancelIoEx能够取消给定文件句柄的一个指定IO请求。它会将hFile设备待处理的IO请求中所有与pOverlapped相关联的请求都标记为已经取消。由于每个待处理的IO请求都应该有自己的OVERLAPPED结构,因此每次调用CancelIoEx只取消一个待处理的请求。如果pOverlappedNULL,那么CancelIoEx会将hFile指定的设备的所有待处理IO请求都取消掉。被取消的IO请求会返回错误码ERROR_OPERATION_ABORTED

       BOOL CancelIoEx(HANDLE hFile,LPOVERLAPPED pOverlapped);
    4、接收异步IO请求已完成通知

    现在我们已经知道如何将异步设备IO添加到驱动程序队列中,但是我们还没有介绍驱动程序如何通知我们IO请求已经完成。

    Windows提供了4中方式来接收IO请求已经完成的通知:

    一:触发设备内核对象。对向一个设备同时发出多个IO请求时,这种方法无用。

    二:触发事件内核对象。

    三:使用可提醒IO

    四:使用IO完成端口。

    转载出处:http://blog.csdn.net/ithzhang/article/details/8316171

              http://blog.csdn.net/ithzhang/article/details/8508161


    展开全文
  • WINDOWS重叠IO模型

    千次阅读 2012-05-18 16:17:37
    应用程序在单个套接字上投递一个或者多个IO操作,当IO操作完成时对应的重叠数据结构中的事件对象会受信,相应的应用程序通过查事件对象可以得到通知。就这样,通过重叠的数据结构将异步的IO和程序连接起来了。  ...
        

    一. 重叠IO模型简介

    重叠IO的核心实际上就是一个重叠的数据结构。应用程序在单个套接字上投递一个或者多个IO操作,当IO操作完成时对应的重叠数据结构中的事件对象会受信,相应的应用程序通过查事件对象可以得到通知。就这样,通过重叠的数据结构将异步的IO和程序连接起来了。

       重叠数据结构:

     

    typedef struct _OVERLAPPED{

          DWORD Internal;

          DWORD InternalHigh;

          DWORD Offset;

          DWORD OffsetHigh;

          HANDLE hEvent; //核心的参数,这个就是连接异步IO和应用程序的桥梁

    }OVERLAPPED, *LPOVERLAPPED;

    二.重叠IO模型的优点

        1.可以运行在支持winsock2的所有windows平台上(IOCP只能运行在NT平台上)

        2.比起阻塞,select,WSAAsyncSelect以及WSAEventSelect等模型提供了更好的系统级性能。

        3.使用重叠模型的应用程序通知缓冲区收发系统直接使用数据,也就是说,如果应用程序投递了一个10KB大小的缓冲区来接收数据,且数据已经到达套接字,则该数据直接    被拷贝到投递的缓冲区。(这一点和以上四种模型是截然不同的)

    三。重叠IO机制的基本步骤

         1.要使用重叠数据结构我们就要使用新的IO函数(也就是send,recv,sendto,recvfrom要被WSASend(),WSARecv(),WSASendto(),WSARecvfrom(),WSAAccept()代替)。

         2.将WINDOWS事件对象与重叠数据结构相关联

         3.使用1中说的函数在套接字上投递IO请求

         4.不断的查询与重叠数据结构关联在一起的事件对象

        5.获得IO结果,处理结果。

    四。废话少说直接上代码

         注意:这里是一份单线程的代码,所以它做多同时支持64个socket连接,如需更多的连接请采用线程池。

     

     

    #include "initsock.h"
    #include <Mswsock.h>
    #include "stdio.h"
    #include <windows.h>
    
    
    CInitSock theSock;  //主要用来初始化socket库
    #define BUFFER_SIZE 1024
    
    
    //这里是与套接字相关的信息
    typedef struct _SOCKET_OBJ
    {
    	SOCKET s;
    	int nOutstandingOps;  //此套接字上重叠IO的数量
    	LPFN_ACCEPTEX lpfnAcceptEx;  //AcceptEx()函数的指针(仅对于监听套接字而言)
    }SOCKET_OBJ,*PSOCKET_OBJ;
    
    typedef struct _BUFFER_OBJ
    {
    	OVERLAPPED ol;  //重叠的数据结构
    	char* buff;   //投递IO请求时使用的缓冲区结构
    	int nLen;    //缓冲区结构的长度
    
    	PSOCKET_OBJ   pSocket;  //SOCKET结构
    	int nOperation;  //提交的操作类型
    #define OP_ACCEPT  1
    #define OP_READ    2
    #define OP_WRITE   3
    	SOCKET   sAccept;   //客户端套接字,仅对于监听套接字而言
    	_BUFFER_OBJ *pNext;
    
    }BUFFER_OBJ,*PBUFFER_OBJ;
    
    HANDLE g_events[WSA_MAXIMUM_WAIT_EVENTS];
    int g_nBufferCount;
    PBUFFER_OBJ g_pBufferHead,g_pBufferTail;
    
    //申请套接字结构
    PSOCKET_OBJ GetSocketObj(SOCKET s)
    {
    	PSOCKET_OBJ pSocket=(PSOCKET_OBJ)::GlobalAlloc(GPTR,sizeof(SOCKET_OBJ));
    	if(pSocket!=NULL)
    		pSocket->s=s;
    	return pSocket;
    }
    void FreeSocketObj(PSOCKET_OBJ pSocket)
    {
    	if(pSocket->s!=INVALID_SOCKET)
    		::closesocket(pSocket->s);
    	::GlobalFree(pSocket);
    }
    
    PBUFFER_OBJ GetBufferObj(PSOCKET_OBJ pSocket,ULONG nLen)
    {
    	if(g_nBufferCount>WSA_MAXIMUM_WAIT_EVENTS-1)
    		return NULL;
    	PBUFFER_OBJ pBuffer=(PBUFFER_OBJ)::GlobalAlloc(GPTR,sizeof(BUFFER_OBJ));
    	if(pBuffer!=NULL)
    	{
    		pBuffer->buff=(char*)::GlobalAlloc(GPTR,nLen);
    		pBuffer->ol.hEvent=WSACreateEvent();
    		pBuffer->pSocket=pSocket;
    		pBuffer->sAccept=INVALID_SOCKET;
    
    		if(g_pBufferHead==NULL)
    		{
    			g_pBufferHead=g_pBufferTail=pBuffer;
    		}
    		else
    		{
    			g_pBufferTail->pNext=pBuffer;
    			g_pBufferTail=pBuffer;
    		}
    		g_events[++g_nBufferCount]=pBuffer->ol.hEvent;
    	}
    	return pBuffer;
    }
    
    void FreeBufferObj(PBUFFER_OBJ pBuffer)
    {
    	PBUFFER_OBJ pTest=g_pBufferHead;
    	BOOL bFind=FALSE;
    	if(pTest==pBuffer)  //这边难道不会造成内存泄露吗?
    	{
    		g_pBufferHead=g_pBufferTail=NULL;
    		bFind=TRUE;
    	}
    	else
    	{
    		while(pTest!=NULL&&pTest->pNext!=pBuffer)
    		{
    			pTest=pTest->pNext;
    		}
    		if(pTest!=NULL)
    		{
    			pTest->pNext=pBuffer->pNext;
    			if(pTest->pNext==NULL)
    				g_pBufferTail=pTest;
    			bFind=TRUE;
    		}
    	}
    	if(bFind)
    	{
    		g_nBufferCount--;
    		::CloseHandle(pBuffer->ol.hEvent);
    		::GlobalFree(pBuffer->buff);
    		::GlobalFree(pBuffer);
    	}
    }
    
    void RebuildArray()
    {
    	PBUFFER_OBJ pBuffer = g_pBufferHead;
    	int i =  1;
    	while(pBuffer != NULL)
    	{
    		g_events[i++] = pBuffer->ol.hEvent;
    		pBuffer = pBuffer->pNext;
    	}
    }
    PBUFFER_OBJ FindBufferObj(HANDLE hEvent)
    {
    	PBUFFER_OBJ pBuffer=g_pBufferHead;
    	while(pBuffer!=NULL)
    	{
    		if(pBuffer->ol.hEvent==hEvent)
    			break;
    		pBuffer=pBuffer->pNext;
    	}
    	return pBuffer;
    }
    /*
    后面有对AcceptEx这个函数进行说明
    */
    BOOL PostAccept(PBUFFER_OBJ pBuffer)
    {
    	PSOCKET_OBJ pSocket=pBuffer->pSocket;
    	if(pSocket->lpfnAcceptEx!=NULL)
    	{
    		pBuffer->nOperation=OP_ACCEPT;
    		pSocket->nOutstandingOps++;
    
    		//投递此IO请求
    		DWORD dwBytes;
    		pBuffer->sAccept=::WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
                    //注意:AcceptEx()如果提供了第四个参数,则这个函数会一直等到得到第一块数据才会返回。
    		BOOL b=pSocket->lpfnAcceptEx(pSocket->s,pBuffer->sAccept,pBuffer->buff,BUFFER_SIZE-((sizeof(sockaddr_in)+16)*2),sizeof(sockaddr_in)+16,
    			sizeof(sockaddr_in)+16,&dwBytes,&pBuffer->ol);
    		if(!b)
    		{
    			if(::WSAGetLastError()!=WSA_IO_PENDING)
    				return false;
    		}
    		return true;
    	}
    	return false;
    }
    BOOL PostRecv(PBUFFER_OBJ pBuffer)
    {
    	pBuffer->nOperation=OP_READ;
    	pBuffer->pSocket->nOutstandingOps++;
    
    	DWORD dwBytes;
    	DWORD dwFlags=0;
    	WSABUF buf;
    	buf.buf=pBuffer->buff;
    	buf.len=pBuffer->nLen;
    	if(::WSARecv(pBuffer->pSocket->s,&buf,1,&dwBytes,&dwFlags,&pBuffer->ol,NULL)!=NO_ERROR)
    	{
    		if(::WSAGetLastError()!=WSA_IO_PENDING)
    			return false;
    	}
    	return true;
    }
    BOOL PostSend(PBUFFER_OBJ pBuffer)
    {
    	pBuffer->nOperation=OP_WRITE;
    	pBuffer->pSocket->nOutstandingOps++;
    
    	DWORD dwBytes;
    	DWORD dwFlags=0;
    	WSABUF buf;
    	buf.buf=pBuffer->buff;
    	buf.len=pBuffer->nLen;
    	if(::WSASend(pBuffer->pSocket->s,&buf,1,&dwBytes,dwFlags,&pBuffer->ol,NULL)!=NO_ERROR)
    	{
    		if(::WSAGetLastError()!=WSA_IO_PENDING)
    			return false;
    	}
    	return true;
    }
    
    //最重要的函数:IO处理函数
    
    BOOL HandleIO(PBUFFER_OBJ pBuffer)
    {
    	PSOCKET_OBJ pSocket=pBuffer->pSocket;
    	pSocket->nOutstandingOps--;
    
    
    	DWORD dwTrans;
    	DWORD dwFlags;
    	BOOL Ret=::WSAGetOverlappedResult(pBuffer->pSocket->s,&pBuffer->ol,&dwTrans,FALSE,&dwFlags);
    	if(!Ret)
    	{
    		if(pSocket->s!=INVALID_SOCKET)
    		{
    			::closesocket(pSocket->s);
    			pSocket->s=INVALID_SOCKET;
    		}
    		if(pSocket->nOutstandingOps==0)
    			FreeSocketObj(pSocket);
    		FreeBufferObj(pBuffer);
    		return FALSE;
    	}
    
    	switch(pBuffer->nOperation)
    	{
    	case OP_ACCEPT:
    		{
    			PSOCKET_OBJ pClient=GetSocketObj(pBuffer->sAccept);
    			PBUFFER_OBJ pSend=GetBufferObj(pClient,BUFFER_SIZE);
    			if(pSend==NULL)
    			{
    				printf("Too much  connections!");
    				FreeSocketObj(pClient);
    				return FALSE;
    			}
    			RebuildArray();
    			pSend->nLen=dwTrans;
    			memcpy(pSend->buff,pBuffer->buff,dwTrans);
    
    
    			if(!PostSend(pSend))
    			{
    				FreeSocketObj(pClient);
    				FreeBufferObj(pSend);
    				return FALSE;
    			}
    			PostAccept(pBuffer);
    		}
    		break;
    	case OP_READ:
    		if(dwTrans>0)
    		{
    			PBUFFER_OBJ pSend=pBuffer;
    			pBuffer->nLen=dwTrans;
    			PostSend(pSend);
    		}
    		else
    		{
    			if(pSocket->s!=INVALID_SOCKET)
    			{
    				::closesocket(pSocket->s);
    				pSocket->s=INVALID_SOCKET;
    			}
    			if(pSocket->nOutstandingOps==0)
    				FreeSocketObj(pSocket);
    			FreeBufferObj(pBuffer);
    			return FALSE;
    		}
    		break;
    	case OP_WRITE:
    		if(dwTrans>0)
    		{
    			pBuffer->nLen=BUFFER_SIZE;
    			PostRecv(pBuffer);
    		}
    		else
    		{
    			if(pSocket->s!=INVALID_SOCKET)
    			{
    				::closesocket(pSocket->s);
    				pSocket->s=INVALID_SOCKET;
    			}
    			if(pSocket->nOutstandingOps==0)
    				FreeSocketObj(pSocket);
    			FreeBufferObj(pBuffer);
    			return FALSE;
    		}
    		break;
    
    	}
    	return TRUE;
    }
    void main()
    {
    	// 创建监听套节字,绑定到本地端口,进入监听模式
    	int nPort = 4567;
    	SOCKET sListen = 
    		::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
    	SOCKADDR_IN si;
    	si.sin_family = AF_INET;
    	si.sin_port = ::ntohs(nPort);
    	si.sin_addr.S_un.S_addr = INADDR_ANY;
    	::bind(sListen, (sockaddr*)&si, sizeof(si));
    	::listen(sListen, 200);
    
    	// 为监听套节字创建一个SOCKET_OBJ对象
    	PSOCKET_OBJ pListen = GetSocketObj(sListen);
    
    	// 加载扩展函数AcceptEx
    	GUID GuidAcceptEx = WSAID_ACCEPTEX;
    	DWORD dwBytes;
    	WSAIoctl(pListen->s, 
    		SIO_GET_EXTENSION_FUNCTION_POINTER, 
    		&GuidAcceptEx, 
    		sizeof(GuidAcceptEx),
    		&pListen->lpfnAcceptEx, 
    		sizeof(pListen->lpfnAcceptEx), 
    		&dwBytes, 
    		NULL, 
    		NULL);
    
    	// 创建用来重新建立g_events数组的事件对象
    	g_events[0] = ::WSACreateEvent();
    
    	// 在此可以投递多个接受I/O请求
    	for(int i=0; i<5; i++)
    	{
    		PostAccept(GetBufferObj(pListen, BUFFER_SIZE));
    	}
    	::WSASetEvent(g_events[0]);
    	
    	while(TRUE)
    	{
    		int nIndex = 
    			::WSAWaitForMultipleEvents(g_nBufferCount + 1, g_events, FALSE, WSA_INFINITE, FALSE);
    		if(nIndex == WSA_WAIT_FAILED)
    		{
    			printf("WSAWaitForMultipleEvents() failed \n");
    			break;
    		}
    		nIndex = nIndex - WSA_WAIT_EVENT_0;
    		for(int i=0; i<=nIndex; i++)
    		{
    			int nRet = ::WSAWaitForMultipleEvents(1, &g_events[i], TRUE, 0, FALSE);
    			if(nRet == WSA_WAIT_TIMEOUT)
    				continue;
    			else
    			{
    				::WSAResetEvent(g_events[i]);
    				// 重新建立g_events数组
    				if(i == 0)
    				{
    					RebuildArray();
    					continue;
    				}
    
    				// 处理这个I/O
    				PBUFFER_OBJ pBuffer = FindBufferObj(g_events[i]);
    				if(pBuffer != NULL)
    				{
    					if(!HandleIO(pBuffer))
    						RebuildArray();
    				}
    			}
    		}
    	}
    }

     

       

    展开全文
  • IO_COUNTERS io_counter; if(GetProcessIoCounters(GetCurrentProcess(), &io_counter)) { if(read_bytes) *read_bytes = io_counter.ReadTransferCount; if(write_bytes) *write_bytes = io_counter....

    https://whyabc.iteye.com/blog/2002685

    process_stat.h:

    * @brief 进程统计信息函数的声明 
    #ifndef PROCESS_STAT_H  
    #define PROCESS_STAT_H  
      
    #ifdef __cplusplus  
    extern "C" {  
    #endif  
    
        typedef long long           int64_t;  
        typedef unsigned long long  uint64_t;  
      
        /// 获取当前进程的cpu使用率,返回-1失败  
        int get_cpu_usage();
      
        /// 获取当前进程内存和虚拟内存使用量,返回-1失败,0成功  
        int get_memory_usage(uint64_t* mem, uint64_t* vmem);
      
        /// 获取当前进程总共读和写的IO字节数,返回-1失败,0成功  
        int get_io_bytes(uint64_t* read_bytes, uint64_t* write_bytes);  
      
    #ifdef  __cplusplus  
    }  
    #endif  
      
    #endif

    process_stat.cpp:

    * @brief 进程统计信息函数的实现 
    * 需要连接到psapi.lib 
      
    #include <windows.h>  
    #include <psapi.h>  
    #include <assert.h>  
    #include "process_stat.h"  
      
    /// 时间转换  
    static uint64_t file_time_2_utc(const FILETIME* ftime)  
    {  
        LARGE_INTEGER li;  
      
        assert(ftime);  
        li.LowPart = ftime->dwLowDateTime;  
        li.HighPart = ftime->dwHighDateTime;  
        return li.QuadPart;  
    }  
      
    /// 获得CPU的核数  
    static int get_processor_number()  
    {  
        SYSTEM_INFO info;  
        GetSystemInfo(&info);  
        return (int)info.dwNumberOfProcessors;  
    }  
      
    int get_cpu_usage()  
    {  
        //cpu数量  
        static int processor_count_ = -1;  
        //上一次的时间  
        static int64_t last_time_ = 0;  
        static int64_t last_system_time_ = 0;  
      
        FILETIME now;  
        FILETIME creation_time;  
        FILETIME exit_time;  
        FILETIME kernel_time;  
        FILETIME user_time;  
        int64_t system_time;  
        int64_t time;  
        int64_t system_time_delta;  
        int64_t time_delta;  
      
        int cpu = -1;  
      
        if(processor_count_ == -1)  
        {  
            processor_count_ = get_processor_number();  
        }  
      
        GetSystemTimeAsFileTime(&now);  
      
        if (!GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,  
            &kernel_time, &user_time))  
        {  
            // We don't assert here because in some cases (such as in the Task Manager)  
            // we may call this function on a process that has just exited but we have  
            // not yet received the notification.  
            return -1;  
        }  
    system_time=(file_time_2_utc(&kernel_time)+file_time_2_utc(&user_time))/processor_count_;  
        time = file_time_2_utc(&now);  
      
        if ((last_system_time_ == 0) || (last_time_ == 0))  
        {  
            // First call, just set the last values.  
            last_system_time_ = system_time;  
            last_time_ = time;  
            return -1;  
        }  
      
        system_time_delta = system_time - last_system_time_;  
        time_delta = time - last_time_;  
      
        assert(time_delta != 0);  
      
        if (time_delta == 0)  
            return -1;  
      
        // We add time_delta / 2 so the result is rounded.  
        cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta);  
        last_system_time_ = system_time;  
        last_time_ = time;  
        return cpu;  
    }  
      
    int get_memory_usage(uint64_t* mem, uint64_t* vmem)  
    {  
        PROCESS_MEMORY_COUNTERS pmc;  
        if(GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))  
        {  
            if(mem) *mem = pmc.WorkingSetSize;  
            if(vmem) *vmem = pmc.PagefileUsage;  
            return 0;  
        }  
        return -1;  
    }  
      
    int get_io_bytes(uint64_t* read_bytes, uint64_t* write_bytes)  
    {  
        IO_COUNTERS io_counter;  
        if(GetProcessIoCounters(GetCurrentProcess(), &io_counter))  
        {  
            if(read_bytes) *read_bytes = io_counter.ReadTransferCount;  
            if(write_bytes) *write_bytes = io_counter.WriteTransferCount;  
            return 0;  
        }  
        return -1;  
    }

    main.cpp

    * @brief 进程统计信息函数的测试 
      
    #include "process_stat.h"  
    #include <stdio.h>  
    #include <Windows.h>  
      
    int main()   
    {   
        while(1)   
        {  
            int cpu;  
            uint64_t mem, vmem, r, w;  
      
            cpu = get_cpu_usage();  
            get_memory_usage(&mem, &vmem);  
            get_io_bytes(&r, &w);  
      
            printf("CPU使用率: %u\n",cpu);  
            printf("内存使用: %u 字节\n", mem);  
            printf("虚拟内存使用: %u 字节\n", vmem);  
            printf("总共读: %u 字节\n", r);  
            printf("总共写: %u 字节\n", w);   
      
            Sleep(1000);   
        }   
        return 0;   
    }
    

    注:需要用到psapi.h和psapi.lib文件。

    展开全文
  • Windows异步IO(Asynchronous IO) (一)

    千次阅读 2010-01-29 13:14:00
    题记:最近在学习Windows SDK编程,打算在这里贴出自己的学习总结和心得与大家交流,主要参考资料来自和。我尽量用英文术语来表达技术概念,方便大家查找其它资料。第一篇从异步IO(Asynchronous IO)说起,以文件IO...

    题记:最近在学习Windows SDK编程,打算在这里贴出自己的学习总结和心得与大家交流,主要参考资料来自<Windows via C/C++ 5th>和<Programming Windows>。我尽量用英文术语来表达技术概念,方便大家查找其它资料。第一篇从异步IO(Asynchronous IO)说起,以文件IO作为代表。

     

        异步IO是现代操作系统必不可少的特性,它让宝贵的CPU计算资源不会浪费在等待慢速IO上。它的行为方式很直观,用户线程在发送IO请求(Issue IO Request)后不用一直挂起,直到IO完成,而是直接返回继续执行其它任务。在设备驱动(Device Driver)完成IO请求后,会通知用户线程数据传输已完成,可以进行相关操作。Windows异步IO的过程主要有两步:1)向设备驱动发送IO请求,2)设备驱动在完成IO请求后通知用户已完成数据传输,即完成通知(Completion Notification)。这一篇主要介绍第一步:发送IO请求。

     

        Windows SDK中关于文件异步IO的操作,主要涉及这样几个基本函数CreateFile,ReadFile,WriteFile。

        1,  

            此函数用于打开一个设备,当然包括文件。当准备发送一个异步IO请求时,必须在dwFlagsAndAttributes参数中指定FILE_FLAG_OVERLAPPED标志,这样告诉系统你想要以异步的方式访问设备。

        2,

            大家都会使用这两个函数进行同步IO,比如:

           

            这里的pOverlapped参数设为NULL。而在进行异步IO时,必须通过这个参数给这个IO请求指定一个OVERLAPPED结构,数据成员如下:

           

            其中:

            Internal                    作为输出参数,返回这次IO请求的错误码。

            InternalHigh             作为输出参数,返回这次IO请求的读写的字节数。

            Offset和OffsetHigh    作为输入参数,指定此次IO请求的起始偏移。这个与同步IO不同:对于每个文件核心对象(File Kernel Object),所有IO请求都依次执行,不能重叠(Overlapped名称的由来),每次IO的起始偏移由文件核心对象的文件指针指定。但在异步IO中,多个IO请求可能重叠进行,这样,文件核心对象中的文件指针是没有意义的,所以每个IO请求必须在Overlapped结构中单独指定起始偏移。

            hEvent                      作为输入参数,用于完成通知(Completion Notification)。以后会详细讲到。

            由上面的功能可看出,Overlapped提供的信息几乎覆盖了一个IO请求的方方面面,事实上,每一个IO请求都对应一个Overlapped,它是用户与设备驱动通信的通道。因此,在整个IO请求完成前,Overlapped结构必须一直有效。

            用户在用ReadFile/WriteFile向设备驱动发送IO请求后,必须仔细对函数返回值进行检查:

            1)若返回非0值,表示IO请求立即完成并返回,此时IO请求并没有进入请求队列。这对异步IO请求是完全可能的,因为系统以前可能刚好缓存(cache)了用户此时请求的内容,所以可以可以马上完成请求。

            2)若返回FALSE,则必须马上调用GetLastError进一步判断。如果GetLastError返回ERROR_IO_PENDING,表明此IO请求成功加入请求队列。如果返回其它值,表明此IO请求不能被加入请求队列,下面是常见的加入请求失败的返回值:

            ERROR_INVALID_USER_BUFFER/ERROR_NOT_ENOUGH_MEMORY 表明队列已满,无法加入新的请求。参考代码:

           

            我们前面说过,Overlapped结构中的Internal成员是作为此次IO请求的错误码返回,所以我们可以通过检查此变量判断目前IO请求的状态。我们在发送IO请求后,如果此请求被成功加入队列,Overlapped结构中的Internal变量会被设为STATUS_PENDING。事实上Windows为我们提供了一个宏:

           

            Overlapped提供几乎所有我们需要的信息,这也充分说明了它是用户与设备驱动进行通信的通道。

    展开全文
  • WindowsIO读写操作

    千次阅读 2019-09-21 11:44:59
    WindowsIO读写操作 使用三个函数:CreateFile,ReadFile,WriteFile,具体使用百度查找 1,CreateFile函数需要注意一些属性问题,例如文件是否可读写,是否写缓冲区,需要和后面的ReadFile,WriteFile想对应起来。...
  • 1,可以通过cmd的perfmon进入2,添加计数器:process,processor、memory、network interface 、 physicaldisk3,然后在下面就可以监控了。 转载于:https://blog.51cto.com/13693838/2368663...
  •  IO_COUNTERS io_counter;  if(GetProcessIoCounters(GetCurrentProcess(), &io_counter))  {  if(read_bytes) *read_bytes = io_counter.ReadTransferCount;  if(write_bytes) *write_bytes = io_counter....
  • zabbix 监控windows 磁盘io

    千次阅读 2017-10-25 11:09:26
    widnows 的性能计数器中可以查看到磁盘io 的性能参数值,下面自定义监控获取性能计数器中磁盘io 的值  在 windows 的zabbix 客户端配置文件中加上自定义 PerfCounter=Disk_Write_Bytes,"\PhysicalDisk(0 C: D:)\...
  • windows下如何查看磁盘IO性能

    万次阅读 2016-09-21 16:14:59
    通常,我们很容易观察到数据库服务器的内存和CPU压力。但是对I/O压力没有直观的判断方法。磁盘有两个重要的参数: Seek time、 Rotational latency。正常的I/O计数为:①...理论情况下,磁盘的随机读计数为125、顺
  • ProcessState.h #ifndef PROCESS_STAT_H #define PROCESS_STAT_H #ifdef __cplusplus extern “C” { #endif typedef long long int64_t;...typedef unsigned long long .../// 获取当前进程的cpu使用率,返回-1失败
  • Windows异步IO (Asynchronous IO) (二)

    千次阅读 2010-01-30 13:23:00
    前一篇文章我们知道如何向设备驱动发送异步IO请求。显然,仅仅知道这些肯定是不够的,...Windows提供四种方法来接受来自设备驱动的完成通知。 也许有朋友已经想到了一个方法。前一篇提到,我们可以通过Overlapped的Int
  • 在之前的《网络编程(16)—— IO复用技术之select》一文中我们介绍了在Linux使用Select进行IO复用的方法。本文对其原理不再详述,旨在通过对比使用加强对select的理解和应用。整个Windows版的select服务端的代码...
  • Windows异步IO四种方式

    千次阅读 2017-02-28 17:27:32
      我们知道,相对于计算机执行的其他操作而言,设备IO(文件、... 在进行异步IO时,我们先向系统发出IO请求,操作系统队列化各种IO请求,并在内部完成操作,当系统在处理IO请求时,我们的线程可以返回继续执行
  • io.h 头文件内容:/*io.h - declarations for low-level file handling and I/O functions * * Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: * This file contains the function d...
  • Windows 异步IO和 完成端口(IOCP)

    千次阅读 2012-07-26 23:16:32
    见过网上好多的完成端口和网络通信的文章,呵呵,这里就简单的说说文件异步IO和完成端口,这里仅仅说说读取操作。下面是一些总结,很少有人提及,认真的看过MSDN文档之后得出的,欢迎指正。 要对文件异步IO操作,...
  • Windows 异步IO的几种实现方式

    万次阅读 2015-03-26 18:00:30
    Windows上的异步IO有好几种实现方式。 设备内核对象 这是最简单的一种了,直接用设备内核对象的状态。比如文件句柄,线程句柄等等,这些内核对象都是有一个触发状态的,比如当一个线程结束后,线程内核对象就...
  • //FILE_FLAG_OVERLAPPED 允许异步IO,即重叠方式 hPipe = CreateNamedPipe(L"////.//pipe//namedpipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, &sa); if ( INVALID_HANDLE_...
  • Windows下socket.io环境搭建与使用(做一个一对一聊天程序)
  • Windows的6种IO模型

    千次阅读 2009-08-26 11:05:00
    WindowsIO模型比较特殊,有6种: 一:select模型 二:WSAAsyncSelect模型 三:WSAEventSelect模型 四:Overlapped I/O 事件通知模型 五:Overlapped I/O 完成例程模型 六:IOCP模型
  • 使用Tomcat Native提升Tomcat IO效率

    万次阅读 热门讨论 2020-12-11 22:41:39
    IO有很多种,从最开始的Block IO,到nonblocking IO,再到IO多路复用和异步IO,一步一步的将IO的性能提升做到极致。 今天我们要介绍一下怎么使用Tomcat Native来提升Tomcat IO的效率。
  • windows下6种IO模型

    千次阅读 2017-07-31 11:22:06
    windows提供了一些I/O 模型帮助应用程序以同步或者异步方式在一个或者多个套接字上管理I/O。大体上,这样的I/O 模型共有6 种。 阻塞(blocking)模型 选择(select)模型 WSAAsyncSelect模型 WSAEventSelect ...
  • Windows socket之重叠IO:事件通知

    千次阅读 2013-01-12 14:56:18
    Windows socket重叠IO模型开发。 利用套接字重叠IO模型,应用程序能一次投递一个或多个IO请求,当系统完成IO操作后通知应用程序。该模型以win32异步IO机制为基础。与前面介绍的所有IO模型相比较,该模型是真正意义...
  • Drawio使用简介(慢慢更新中)

    千次阅读 多人点赞 2021-04-22 17:49:02
    支持网页版使用(网页版可以自己部署一套)以及客户端使用(支持windows,MacOS以及Linux)。 该项目开源在github上的源码:https://github.com/jgraph/drawio-desktop 目录网页端使用桌面端下载语言设置开始绘图...
  • 监控Windows-CPU使用率 监控Windows-磁盘IO性能监控 监控Windows/Linux-磁盘触发器阈值更改 监控Windows-网卡自动发现规则 配置服务端邮件报警功能   1、Windows服务器需要先安装zabbix-agent代理 Zabbix-agent...
  • 当linux报OOM时,意味着整个系统的内存已经不足,如果不杀死进程的话...OOM Killer 会在系统报OOM的时候,杀死当前score最高的进程,一般情况也就是占用内存最大的进程。 解决方法:一是增加系统内存,二是优化进程...
  • 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行。   异步IO是指:线程发起IO请求后并不会挂起而是继续执行。IO完毕后会得到设备的通知。而IO完成端口就是实现这种通知的很好的一种方式。   线程...
  • windows Socket编程之重叠IO模型

    千次阅读 2016-08-14 15:17:03
    上一篇文章我们讲了EventSelect网络模型,它已经解决了等待数据到来的这一大部分时间,但是它还有一小部分时间没有节省下来。那就是把数据从网卡的缓冲...而这一篇的重叠IO模型就是将这一小部分的时间也给节省了下来。
  • piap.windows io 监测attilax总结

    千次阅读 2013-10-27 00:18:14
    piap.windows io 监测attilax总结 当硬盘光狂闪的时候. 主要目标:找出哪个进程占用io最多, 作者Attilax 艾龙, EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net/attilax ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 347,284
精华内容 138,913
关键字:

windows查看io使用情况