杀死正在执行 memcpy 的线程是不是安全?

Posted

技术标签:

【中文标题】杀死正在执行 memcpy 的线程是不是安全?【英文标题】:Is it safe to kill a thread that is executing a memcpy?杀死正在执行 memcpy 的线程是否安全? 【发布时间】:2018-02-10 18:53:17 【问题描述】:

上下文:

我正在开发一个需要快速访问大文件的应用程序,因此我使用了内存映射。结果,阅读和写作变成了一个简单的memcpy。我现在正在尝试添加中止任何正在进行的读取或写入的功能。

首先想到的(因为我不知道任何可中断的 memcpy 函数)是定期memcpy 几个 KB 并检查是否应该中止操作。如果读取速度相当快,这应该可以确保近乎即时的流产。

如果不是,那么应用程序不应该花费很长时间才能中止,所以我的第二个想法是使用多线程。 memcpy 发生在它自己的线程中,控制线程使用WaitForMultipleObjects 处理一个表明流产的事件,以及 memcpy 线程。如果发出了流产事件的信号,它将杀死 memcpy 线程。但是,documentation on TerminateThread 声明应该绝对确保不会因为不释放资源而使系统处于不良状态。

问题:

在复制映射内存时,memcpy 是否会导致杀死它不安全?这样做安全吗?它是否依赖于实现(使用不同于 Windows x86-64 的操作系统/架构)?


我确实意识到使用第二种方法可能完全是矫枉过正,因为实际上没有 1KB 读/写会花费那么长时间,但我只想安全。

【问题讨论】:

有一种观点认为你不应该终止线程。 考虑将memcpy 以合理大小(例如兆字节)的块进行,其副本通常会持续几毫秒。您可以在复制一些原子标志之后进行测试,或者使用互斥锁等保护该副本......并围绕它进行循环。 这家伙比我知道(很多)“还有人认为调用 TerminateThread 有有效的场景。”:blogs.msdn.microsoft.com/oldnewthing/20150814-00/?p=91811 好的,所以我想这个故事的寓意是:“memcpy 无关紧要,TerminateThread 只是一个可怕的想法”?那就轮询吧! 如果您将使用 ReadFile/WriteFile 代替异步文件句柄,您可以随时中断/取消读/写操作 【参考方案1】:

如果可能你应该选择不同的设计,TerminateThread 不应该被认为是一个正常的功能,它更多的是用于调试/电动工具。

我建议您围绕 memcpy 创建一个包装器,以块的形式进行复制。块大小实际上取决于您,取决于您的响应能力要求。 1 MiB 可能是一个很好的起点。

如果您绝对想杀死线程,您必须考虑以下几点:

您显然不知道 memcpy 在内部是如何工作的,也不知道它复制了多少,因此您必须假设在中止时整个范围都未定义。 在某些版本的 Windows 上终止线程会泄漏内存。有workarounds。 不要在线程中持有任何锁。

【讨论】:

以上是关于杀死正在执行 memcpy 的线程是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

相邻内存区域上的 memcpy() 安全性

安全执行不受信任的 Haskell 代码

什么是现代的、可移植的、安全的等价于 C 中编译时检查的 memcpy?

Java 线程安全计数器

单例,多线程,同时保证线程安全,是不是就意味着在执行单例方法时,无法并发?

accept() 线程安全吗?