消息处理程序中的 RAND_event() 会导致 UI 中的小冻结吗?
Can RAND_event() in message handler cause little-freezes in UI?
有一个消息处理程序(在C++生成器中),如下所示:
void __fastcall TMainForm::HandleMessages(tagMSG &Msg, bool &Handled)
{
RAND_event(Msg.message, Msg.wParam, Msg.lParam);
//...
}
RAND_event()
会导致 UI 中的小冻结吗?
谢谢!
编辑:
RAND_event()
来自OpenSSL,以下是它的描述:
RAND_event()
从鼠标等Windows事件中收集熵 移动和其他用户交互。它应该用 发送到窗口的所有消息的 iMsg、wParam 和 lParam 参数 程序。它将估计事件消息中包含的熵 (如果有的话),并将其添加到 PRNG 中。然后,程序可以处理 消息像往常一样。
如有疑问 - 验证源代码。
从cryptorandrand_win.c
(OpenSSL 1.0.2f)
int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
{
double add_entropy = 0;
switch (iMsg) {
case WM_KEYDOWN:
{
static WPARAM key;
if (key != wParam)
add_entropy = 0.05;
key = wParam;
}
break;
case WM_MOUSEMOVE:
{
static int lastx, lasty, lastdx, lastdy;
int x, y, dx, dy;
x = LOWORD(lParam);
y = HIWORD(lParam);
dx = lastx - x;
dy = lasty - y;
if (dx != 0 && dy != 0 && dx - lastdx != 0 && dy - lastdy != 0)
add_entropy = .2;
lastx = x, lasty = y;
lastdx = dx, lastdy = dy;
}
break;
}
readtimer();
RAND_add(&iMsg, sizeof(iMsg), add_entropy);
RAND_add(&wParam, sizeof(wParam), 0);
RAND_add(&lParam, sizeof(lParam), 0);
return (RAND_status());
}
如您所见,这里没有循环,等待或类似的事情,只有一些基本的比较,分配和添加。您还可以自己验证RAND_event()
中使用的一些功能,例如 readtimer()
,但它们也不包含任何可能导致性能显着下降的内容(至少与使用 UI 相比)。
编辑:噢,刚才看到雷米的评论了,我的错。无论如何,我只是将其保留为一个扩展答案(已经作为评论存在),从一点(很少)有点不同的观点。
RAND_event() 会导致 UI 中的小冻结吗?
或。熵是通过RAND_add
添加的,这意味着熵被提取然后消化。因此,每次调用 RAND_add
时都会调用哈希函数。
如果您使用的是默认的 RAND 引擎,则使用的引擎是来自 <openssl src>cryptorandmd_rand.c
的引擎。这意味着RAND_add
调用ssleay_rand_add
。函数如下所示。
如果正在发送大量Windows消息,那么我可以想象桌面在消化熵时变慢的情况。在移动操作系统上,这个问题可能会变得更加严重。分析工具应该能够为您提供更多信息。
我认为可以在 Windows 上RAND_event
进行优化......消息应累积,然后批量添加。也就是说,累积熵,然后在第 8 次、第 16 次或第 32 次调用时调用RAND_add
。
生成器的运行状况不应受到影响,因为向应用程序发送了如此多的 Windows 消息。您可以使用 Spy++ 来了解正在发送的消息数量。
如果您在某处使用RAND_poll
,那么您可能会看到一个明显的块。有关此内容的详细信息,请参阅问题 #2100:由于 OpenSSL 错误跟踪器上的 Heap32Next,RAND_poll Windows 7 上的速度可能会非常慢。
static void ssleay_rand_add(const void *buf, int num, double add)
{
int i, j, k, st_idx;
long md_c[2];
unsigned char local_md[MD_DIGEST_LENGTH];
EVP_MD_CTX m;
int do_not_lock;
if (!num)
return;
/*
* (Based on the rand(3) manpage)
*
* The input is chopped up into units of 20 bytes (or less for
* the last block). Each of these blocks is run through the hash
* function as follows: The data passed to the hash function
* is the current 'md', the same number of bytes from the 'state'
* (the location determined by in incremented looping index) as
* the current 'block', the new key data 'block', and 'count'
* (which is incremented after each use).
* The result of this is kept in 'md' and also xored into the
* 'state' at the same locations that were used as input into the
* hash function.
*/
/* check if we already have the lock */
if (crypto_lock_rand) {
CRYPTO_THREADID cur;
CRYPTO_THREADID_current(&cur);
CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
} else
do_not_lock = 0;
if (!do_not_lock)
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
st_idx = state_index;
/*
* use our own copies of the counters so that even if a concurrent thread
* seeds with exactly the same data and uses the same subarray there's
* _some_ difference
*/
md_c[0] = md_count[0];
md_c[1] = md_count[1];
memcpy(local_md, md, sizeof md);
/* state_index <= state_num <= STATE_SIZE */
state_index += num;
if (state_index >= STATE_SIZE) {
state_index %= STATE_SIZE;
state_num = STATE_SIZE;
} else if (state_num < STATE_SIZE) {
if (state_index > state_num)
state_num = state_index;
}
/* state_index <= state_num <= STATE_SIZE */
/*
* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] are what we
* will use now, but other threads may use them as well
*/
md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
if (!do_not_lock)
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
EVP_MD_CTX_init(&m);
for (i = 0; i < num; i += MD_DIGEST_LENGTH) {
j = (num - i);
j = (j > MD_DIGEST_LENGTH) ? MD_DIGEST_LENGTH : j;
MD_Init(&m);
MD_Update(&m, local_md, MD_DIGEST_LENGTH);
k = (st_idx + j) - STATE_SIZE;
if (k > 0) {
MD_Update(&m, &(state[st_idx]), j - k);
MD_Update(&m, &(state[0]), k);
} else
MD_Update(&m, &(state[st_idx]), j);
/* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */
MD_Update(&m, buf, j);
/*
* We know that line may cause programs such as purify and valgrind
* to complain about use of uninitialized data. The problem is not,
* it's with the caller. Removing that line will make sure you get
* really bad randomness and thereby other problems such as very
* insecure keys.
*/
MD_Update(&m, (unsigned char *)&(md_c[0]), sizeof(md_c));
MD_Final(&m, local_md);
md_c[1]++;
buf = (const char *)buf + j;
for (k = 0; k < j; k++) {
/*
* Parallel threads may interfere with this, but always each byte
* of the new state is the XOR of some previous value of its and
* local_md (itermediate values may be lost). Alway using locking
* could hurt performance more than necessary given that
* conflicts occur only when the total seeding is longer than the
* random state.
*/
state[st_idx++] ^= local_md[k];
if (st_idx >= STATE_SIZE)
st_idx = 0;
}
}
EVP_MD_CTX_cleanup(&m);
if (!do_not_lock)
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
/*
* Don't just copy back local_md into md -- this could mean that other
* thread's seeding remains without effect (except for the incremented
* counter). By XORing it we keep at least as much entropy as fits into
* md.
*/
for (k = 0; k < (int)sizeof(md); k++) {
md[k] ^= local_md[k];
}
if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
entropy += add;
if (!do_not_lock)
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
- 如何在MS Visual Studio 2019中运行QT UI
- 如何处理使用.ui文件生成的.h文件
- WIN32:C++,为什么在WM_CLOSE上调用Messagebox函数程序正在冻结
- 根据变量使Qt UI中的复选框为已选中/未选中
- 一旦双簧管录制开始,主 UI 线程就会被阻止
- Win32 发送输入鼠标移动滞后并冻结
- ImGui 在单击按钮后冻结
- Qt Quick,如何更改 Ui 源代码?
- QWidget UI 在使用 QQuickWidget 时冻结
- 在 3ds Max 中更新进度条后,环境和效果 UI 不刷新
- 如何防止 std::thread 在 QT 中冻结 GUI?
- Adafruit 羽毛RFM69HCW在使用过程中会冻结,需要硬重置
- Qt - QQuickWidget setSource without freezing UI
- MFC/C++ ComboBox:禁用下拉列表关闭和打开(UI 冻结)的绘制
- 在 QThread 中运行长时间操作并将信号发送到主线程仍会冻结 UI
- 消息处理程序中的 RAND_event() 会导致 UI 中的小冻结吗?
- C++程序冻结和UI变为全白
- 当GL更新大于15 Hz时,Qt UI冻结
- 将项目添加到列表控件时,UI被冻结
- C++/MFC - 防止挂起的子控件 (ActiveX) 控件冻结整个 UI