windows异步之APC验证

3 篇文章 0 订阅
2 篇文章 0 订阅
本文通过实验验证了WriteFileEx中OVERLAPPED结构的hEvent事件在I/O完成后并不会自动激发,并探讨了WaitForSingleObjectEx在不同参数下的行为,特别是线程如何被APC(异步过程调用)唤醒。同时,文章提到了使用已激发态事件句柄可能导致的不确定结果。
摘要由CSDN通过智能技术生成
using namespace std;
HANDLE hfile;
OVERLAPPED ov = { 0 };

void __stdcall apc(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
	cout << "enter apc" << endl;
	cout << dwErrorCode << ", " << dwNumberOfBytesTransfered << endl;
}

unsigned __stdcall proc2(void*) {
	cout << "enter thread 22222" << endl;
	WaitForSingleObject(ov.hEvent, INFINITE);
	cout << "thread 2222 have wait event ok..." << endl;
	return 0;
}

unsigned __stdcall proc1(void*) {

	hfile = CreateFile(L"D:\\test.file", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);

	if (hfile == INVALID_HANDLE_VALUE) {
		cout << "create file failed." << endl;
	}

	constexpr int size = 110240000;
	char* buf = new char[size] {0};

	DWORD numsWrite = 0;

	DWORD ret = WriteFileEx(hfile, buf, size, &ov, apc);
	DWORD lastError = GetLastError();

	if (ret == 0) {
		cout << "write failed " << lastError << endl;
		return 0;
	}

	DWORD dw =  WaitForSingleObjectEx(hfile, INFINITE, FALSE);
    //DWORD dw =  WaitForSingleObjectEx(hfile, INFINITE, TRUE);
	//SleepEx(INFINITE, TRUE);
	cout << "after sleep" << endl;
	return 0;
}

int main() {

	ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    //ov.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);

	HANDLE t1 = (HANDLE)_beginthreadex(NULL, 0, proc1, NULL, NULL, NULL);
	HANDLE t2 = (HANDLE)_beginthreadex(NULL, 0, proc2, NULL, NULL, NULL);
	WaitForSingleObject(t1, INFINITE);
	WaitForSingleObject(t2, INFINITE);

    CloseHandle(t1);
    CloseHandle(t2);
	return 0;
}

想验证两个点:

    1.调用WriteFileEx传入OVERLAPPED,其中的hEvent有啥用?会不会完成I/O以后把event变成激发态?

    结果:用proc2测试,如果会将event激发,则会打印两句,结果验证只有一句。这个hEvent没啥用处。书上也写了,哈哈。

    ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    2.WriteFileEx以后调用这三个函数等待有啥不同?

    //DWORD dw =  WaitForSingleObjectEx(hfile, INFINITE, FALSE);
    //DWORD dw =  WaitForSingleObjectEx(hfile, INFINITE, TRUE);
    SleepEx(INFINITE, TRUE);

 

    答案:这个是我一个脑洞。我当时有点不太理解。其实很简单

    WaitForSingleObjectEx(hfile, INFINITE, FALSE);,则退化为WaitForSingleObject(hfile, INIFINITE),而这个等待,其实是对文件的句柄的等待。文件句柄在有异步I/O的情况下是非激发态,I/O完成以后激发态。所以这里实际是windows核心编程里的“触发设备内核对象”,所以返回的是WAIT_OBJECT_0,不推荐。

    WaitForSingleObjectEx(hfile, INFINITE, TRUE);  经过验证,照道理来说,I/O完成以后,此时hfile已经激发了。但是这里由于此时线程处于可提醒状态,实际I/O完成以后,系统往线程插入了APC队列,执行了apc函数,返回了WAIT_IO_COMPLETION(192),wait就结束了。

 SleepEx(INFINITE, TRUE);这个是最正确的调用,本来就跟hfile无关啊。返回的是192,因为apc执行了。

 

最后的脑洞:如果我用一个激发态的event去调用,如下,结果会咋样?

 

验证:结果不定,size=1102400000时,wait 返回了0,显然是event生效了,没有执行apc。

size=11024000(少两个0)的时候,是apc生效了,但是event还是可以继续wait。

结论:我们别这样瞎搞

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值