和完成例程比较。完成端口的效率更高。其主要原因是完成端口可以指定线程池。这么说吧,完成例程,每次只能由一个线程来监控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

使用完成端口监控文件目录的例子相关推荐

  1. 在Zabbix中添加交换机端口监控

    转载来源 : 如何在Zabbix中添加交换机端口监控 :https://www.jianshu.com/p/374c0a992109 交换机上配置snmp,这个不多说了 zabbix服务器上执行如下 ...

  2. Zabbix系统端口监控状态

    一.监控系统Zabbix -添加端口监控 1.监控端口 zabbix监控端口使用如下key: key:net.tcp.listen[port] Checks if this port is in LI ...

  3. python监控端口_python3 端口监控

    原来一直用shell结合nmap做端口监控,最近刚好有时间改用python重写. 监控效果: mysql数据库用于读取IP地址,输出IP详细信息,记录故障时间,send记录是否发生变量. # -*-  ...

  4. Zabbix 添加端口监控链接

    zabbix 添加端口监控 连接数: zabbix  配置  添加 监控项: 其他检测 方式也是 示例: zabbix 客户端配置文件添加: 编辑 zabbix_agentd.conf  添加  端口 ...

  5. 互联网企业安全之端口监控

    外网端口监控系统是整个安全体系中非常重要的一环,它就像眼睛一样,时刻监控外网端口开放情况,并且在发现高危端口时能够及时提醒安全.运维人员做出相应处理. 对安全人员来说,互联网公司在快速发展壮大的过程中 ...

  6. C#实现实时监控文件目录下的变化

    本文主要描述如何通过C#实现实时监控文件目录下的变化,包括文件和目录的添加,删除,修改和重命名等操作. 首先,我们需要对.net提供的FileSystemWatcher类有所了解.我有些懒,找了MSD ...

  7. 3389服务器信息是什么意思,服务器3389端口监控问题

    模仿我上次转发的博文,对3389端口监控问题不通过简单的记录来监控,可以通过向邮箱发送邮件的形式来提醒管理员 ​所需文件:blat邮件发送器 1.先下载 blat解压缩到c盘blat目录下面. 2.任 ...

  8. Zabbix端口监控

    方法一: zabbix-agent端操作,被监控服务器需要先安装zabbix-agent,安装方法见CentOS7安装Zabbix-agent_水煮胡萝卜的博客-CSDN博客 然后继续操作如下: mk ...

  9. linux webservice服务器端,Linux查看资源使用情况 webservice服务端口监控

    本人在最近的项目过程中,发现一个很严重的问题 在我们写的一个应用中,jboss作应用程序的容器,其中加载了webservice服务.每次服务运行一段时间后,大概几天时间以后,发现很奇怪的现象.我们的j ...

最新文章

  1. 重磅 |“金砖”电商报告:5年后金砖五国网络零售将超3万亿美元
  2. pidstat 命令查看某个进程的CPU、内存、磁盘使用情况
  3. 软件开发生命周期模型 瀑布模型、增量模型、原型模型、螺旋模型、喷泉模型总结...
  4. 得意而忘乎形:谈葛水平的水墨画
  5. Datalore:用于机器学习可视化的新Web方案!
  6. iOS基础-高级视图-UITableView--静态单元格
  7. 磁盘剩余空间策略_MySQL磁盘消耗迅猛掌握这点就够了,包你事半功倍
  8. Wireshark文档阅读笔记-TCP 4 times close解析与实例
  9. 【Gitlab+Jenkins+Ansible】构建自动化部署
  10. python生成序列_python中生成一个指定长度的列表,按1,2,3的序列生成
  11. 从头构建自己的Linux系统 -转
  12. macos下如何配置ssh无密码登录
  13. 20145210 20145226实验一
  14. 基于人机环境系统工程的智慧企业建设思考
  15. 无线PLC专用数据终端应用方案
  16. 基于yolov3 v4 v5的电梯轿厢下的电动车目标检测
  17. 思科1242 AP无法连接到无线控制器
  18. java五险一金去从工资扣吗,五险一金需要自己交钱吗?是从工资里扣除还是......
  19. 【先锋】七牛云存储:三年磨一剑及背后核心技术解析
  20. 科学计算机度计算,科学计算器arctan

热门文章

  1. python requests库作用_python Requests库入门
  2. python像素处理_Python+OpenCV图像处理(五)—— 像素运算
  3. Linux非系统盘挂载,[转载] Linux mount 挂载分区、硬盘
  4. html状态查询爱站,批量获取爱站数据
  5. html不用点击自动执行,页面自动执行(加载)js的几种方法
  6. 2020 华工 数据结构-平时作业_【激光】从上海工博会看华工激光的差异化路线...
  7. python中等高线填充颜色_Python matplotlib等高线图对数颜色
  8. 秀操作:函数宏的三种封装方式
  9. 2020 年 4 月编程语言排行榜:C 语言重回王者?
  10. ADC128S022的verilog设计与仿真实现