使用完成端口监控文件目录的例子
和完成例程比较。完成端口的效率更高。其主要原因是完成端口可以指定线程池。这么说吧,完成例程,每次只能由一个线程来监控IO 完成变化。但是完成端口,却可以指定
一堆线程(想象一下一个人干活和一群人干活的区别)轮班的监控,即1号线程忙碌了,2号线程顶上去,如果2号也忙,3号顶上去!这样,效率大大提高。
但是呢,线程的创建和销毁是非常消耗时间的。所以,使用了线程池。另外线程涉及到CPU 上下文的切换问题。所以多线程的数量一般选择2*CPU数量,但这是个经验值
实际情况需要反复测试。
下面是BCB实现效果及源码(参考资料 windows 核心编程 第10章,11章)
2014/12/23更新,增加临界值保证cout的输出不出现乱码
2014/12/23更新,将ReadDirectoryChangesW 的缓冲区,移动到多线程中执行。
1 //--------------------------------------------------------------------------- 2 3 #include <vcl.h> 4 #include <iostream> 5 using namespace std; 6 #pragma hdrstop 7 8 //--------------------------------------------------------------------------- 9 10 #pragma argsused 11 12 HANDLE hMonitorDir = NULL; 13 HANDLE hCompletePort = NULL; 14 //因为cout 不是线程安全的,所以要用临界值 15 CRITICAL_SECTION cs; 16 const DWORD CompleteKey = 1; 17 //让完成端口处理线程池自己决定最多的线程并发数 18 const DWORD MaxThreadCount = 0; 19 DWORD dwByteReturn; 20 OVERLAPPED overlapped={0}; 21 DWORD dwError = 0; 22 int fileCount = 0; 23 24 25 //线程池 26 DWORD WINAPI ThreadProc(LPVOID lpParameter) 27 { 28 DWORD dwTranferBytes = 0; 29 DWORD dwKey = 0; 30 LPOVERLAPPED pOverLapped = &overlapped; 31 //捕获文件信息的缓冲长度 32 DWORD dwBufLen 33 =2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH*sizeof(TCHAR)); 34 //捕获文件信息的缓冲buffer 35 FILE_NOTIFY_INFORMATION* Buffer 36 =(FILE_NOTIFY_INFORMATION*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBufLen); 37 38 //开始监控文件夹 39 if(!ReadDirectoryChangesW(hMonitorDir,Buffer,dwBufLen,TRUE, 40 FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME, 41 &dwByteReturn,&overlapped,NULL)) 42 { 43 dwError = GetLastError(); 44 CloseHandle(hMonitorDir); 45 HeapFree(GetProcessHeap(),0,Buffer); 46 cout<<"监控文件夹失败! "<<SysErrorMessage(dwError).c_str()<<endl; 47 return 0; 48 } 49 50 while(true) 51 { 52 53 //完成端口的关键所在 54 //和完成例程相比,完成端口的优势是可以用线程池来监控IO,效率更高 55 BOOL blOk = GetQueuedCompletionStatus(hCompletePort, 56 &dwTranferBytes, 57 &dwKey, 58 &pOverLapped,INFINITE); 59 60 dwError = GetLastError(); 61 62 if(blOk && CompleteKey == dwKey) 63 { 64 //输出线程编号 65 EnterCriticalSection( &cs ); 66 cout<<"线程号:"<<GetCurrentThreadId()<<endl; 67 LeaveCriticalSection( &cs ); 68 69 //捕获到文件变化 70 FILE_NOTIFY_INFORMATION* notify = Buffer; 71 72 AnsiString fileName = 73 WideCharLenToString( 74 notify->FileName,notify->FileNameLength/2); 75 do 76 { 77 bool blNormal = true; 78 switch(notify->Action) 79 { 80 case FILE_ACTION_ADDED: 81 { 82 EnterCriticalSection( &cs ); 83 cout<<"增加了文件"<<fileName.c_str()<<endl; 84 LeaveCriticalSection( &cs ); 85 } 86 break; 87 case FILE_ACTION_REMOVED: 88 { 89 EnterCriticalSection( &cs ); 90 cout<<"删除了文件"<<fileName.c_str()<<endl; 91 LeaveCriticalSection( &cs ); 92 } 93 break; 94 case FILE_ACTION_MODIFIED: 95 { 96 EnterCriticalSection( &cs ); 97 cout<<"修改了文件"<<fileName.c_str()<<endl; 98 LeaveCriticalSection( &cs ); 99 } 100 break; 101 case FILE_ACTION_RENAMED_OLD_NAME: 102 { 103 EnterCriticalSection( &cs ); 104 cout<<"被重名的文件"<<fileName.c_str()<<endl; 105 LeaveCriticalSection( &cs ); 106 } 107 break; 108 case FILE_ACTION_RENAMED_NEW_NAME: 109 { 110 EnterCriticalSection( &cs ); 111 cout<<"新命名的文件"<<fileName.c_str()<<endl; 112 LeaveCriticalSection( &cs ); 113 } 114 break; 115 default: //有可能已经溢出了! 116 blNormal = false; 117 break; 118 } 119 120 if(!blNormal) 121 { 122 break; 123 } 124 //将指针偏移offset个字节 125 notify = notify + notify->NextEntryOffset; 126 } 127 while(notify->NextEntryOffset>0); 128 129 if(!ReadDirectoryChangesW(hMonitorDir,Buffer,dwBufLen,TRUE, 130 FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME , 131 &dwByteReturn,&overlapped,NULL)) 132 { 133 dwError = GetLastError(); 134 CloseHandle(hMonitorDir); 135 CloseHandle(hCompletePort); 136 HeapFree(GetProcessHeap(),0,Buffer); 137 cout<<"监控文件夹失败! "<<SysErrorMessage(dwError).c_str()<<endl; 138 break; 139 } 140 } 141 else 142 { 143 cout<<"完成端口异常! "<<SysErrorMessage(dwError).c_str()<<endl; 144 CloseHandle(hMonitorDir); 145 CloseHandle(hCompletePort); 146 HeapFree(GetProcessHeap(),0,Buffer); 147 break; 148 } 149 } 150 151 return 0; 152 } 153 154 int main(int argc, char* argv[]) 155 { 156 cout<<"开始监控程序目录!...."<<endl; 157 AnsiString fileName = ExtractFileDir(Application->ExeName); 158 159 //打开目录 160 hMonitorDir=CreateFile(fileName.c_str(), 161 FILE_LIST_DIRECTORY, //表明打开一个目录 162 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, 163 NULL, 164 OPEN_EXISTING, 165 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//FILE_FLAG_OVERLAPPED表示异步模式 166 NULL); 167 dwError = GetLastError(); 168 if (INVALID_HANDLE_VALUE == hMonitorDir) 169 { 170 cout<<"打开文件目录失败! "<<SysErrorMessage(dwError).c_str()<<endl; 171 return 0; 172 } 173 //创建完成端口 174 hCompletePort = 175 CreateIoCompletionPort(hMonitorDir,NULL,CompleteKey,MaxThreadCount); 176 dwError = GetLastError(); 177 if(NULL == hCompletePort) 178 { 179 cout<<"创建完成端口失败! "<<SysErrorMessage(dwError).c_str()<<endl; 180 CloseHandle(hMonitorDir); 181 return 0; 182 } 183 184 InitializeCriticalSection( &cs ); 185 //启动线程池,在线程池中进行IO 完成监控 186 //如果是VISTA 以上级别的操作系统,建议使用 187 //TrySubmitThreadpoolCallback 188 //这里,我启用五个工作线程,但实际上完成端口会自己调剂 189 for(int i = 0; i<5; i++) 190 { 191 QueueUserWorkItem(ThreadProc,NULL,0x00000000|0x00000010); 192 } 193 194 195 196 int i = 0; 197 cin>>i; 198 CloseHandle(hMonitorDir); 199 CloseHandle(hCompletePort); 200 return 0; 201 } 202 //---------------------------------------------------------------------------
转载于:https://www.cnblogs.com/songr/p/4179298.html
使用完成端口监控文件目录的例子相关推荐
- 在Zabbix中添加交换机端口监控
转载来源 : 如何在Zabbix中添加交换机端口监控 :https://www.jianshu.com/p/374c0a992109 交换机上配置snmp,这个不多说了 zabbix服务器上执行如下 ...
- Zabbix系统端口监控状态
一.监控系统Zabbix -添加端口监控 1.监控端口 zabbix监控端口使用如下key: key:net.tcp.listen[port] Checks if this port is in LI ...
- python监控端口_python3 端口监控
原来一直用shell结合nmap做端口监控,最近刚好有时间改用python重写. 监控效果: mysql数据库用于读取IP地址,输出IP详细信息,记录故障时间,send记录是否发生变量. # -*- ...
- Zabbix 添加端口监控链接
zabbix 添加端口监控 连接数: zabbix 配置 添加 监控项: 其他检测 方式也是 示例: zabbix 客户端配置文件添加: 编辑 zabbix_agentd.conf 添加 端口 ...
- 互联网企业安全之端口监控
外网端口监控系统是整个安全体系中非常重要的一环,它就像眼睛一样,时刻监控外网端口开放情况,并且在发现高危端口时能够及时提醒安全.运维人员做出相应处理. 对安全人员来说,互联网公司在快速发展壮大的过程中 ...
- C#实现实时监控文件目录下的变化
本文主要描述如何通过C#实现实时监控文件目录下的变化,包括文件和目录的添加,删除,修改和重命名等操作. 首先,我们需要对.net提供的FileSystemWatcher类有所了解.我有些懒,找了MSD ...
- 3389服务器信息是什么意思,服务器3389端口监控问题
模仿我上次转发的博文,对3389端口监控问题不通过简单的记录来监控,可以通过向邮箱发送邮件的形式来提醒管理员 所需文件:blat邮件发送器 1.先下载 blat解压缩到c盘blat目录下面. 2.任 ...
- Zabbix端口监控
方法一: zabbix-agent端操作,被监控服务器需要先安装zabbix-agent,安装方法见CentOS7安装Zabbix-agent_水煮胡萝卜的博客-CSDN博客 然后继续操作如下: mk ...
- linux webservice服务器端,Linux查看资源使用情况 webservice服务端口监控
本人在最近的项目过程中,发现一个很严重的问题 在我们写的一个应用中,jboss作应用程序的容器,其中加载了webservice服务.每次服务运行一段时间后,大概几天时间以后,发现很奇怪的现象.我们的j ...
最新文章
- 重磅 |“金砖”电商报告:5年后金砖五国网络零售将超3万亿美元
- pidstat 命令查看某个进程的CPU、内存、磁盘使用情况
- 软件开发生命周期模型 瀑布模型、增量模型、原型模型、螺旋模型、喷泉模型总结...
- 得意而忘乎形:谈葛水平的水墨画
- Datalore:用于机器学习可视化的新Web方案!
- iOS基础-高级视图-UITableView--静态单元格
- 磁盘剩余空间策略_MySQL磁盘消耗迅猛掌握这点就够了,包你事半功倍
- Wireshark文档阅读笔记-TCP 4 times close解析与实例
- 【Gitlab+Jenkins+Ansible】构建自动化部署
- python生成序列_python中生成一个指定长度的列表,按1,2,3的序列生成
- 从头构建自己的Linux系统 -转
- macos下如何配置ssh无密码登录
- 20145210 20145226实验一
- 基于人机环境系统工程的智慧企业建设思考
- 无线PLC专用数据终端应用方案
- 基于yolov3 v4 v5的电梯轿厢下的电动车目标检测
- 思科1242 AP无法连接到无线控制器
- java五险一金去从工资扣吗,五险一金需要自己交钱吗?是从工资里扣除还是......
- 【先锋】七牛云存储:三年磨一剑及背后核心技术解析
- 科学计算机度计算,科学计算器arctan
热门文章
- python requests库作用_python Requests库入门
- python像素处理_Python+OpenCV图像处理(五)—— 像素运算
- Linux非系统盘挂载,[转载] Linux mount 挂载分区、硬盘
- html状态查询爱站,批量获取爱站数据
- html不用点击自动执行,页面自动执行(加载)js的几种方法
- 2020 华工 数据结构-平时作业_【激光】从上海工博会看华工激光的差异化路线...
- python中等高线填充颜色_Python matplotlib等高线图对数颜色
- 秀操作:函数宏的三种封装方式
- 2020 年 4 月编程语言排行榜:C 语言重回王者?
- ADC128S022的verilog设计与仿真实现