我想在不使用 for 循环的情况下复制数组的内容。副本是在拥有旋转锁时制作的。
memcpy((有没有可能睡觉?
memcpy
(或一般情况下的任何内存访问(可能发生的情况:
- 如果源或目标的一部分是无法访问(无效(的内存,
memcpy
可能会使进程崩溃,这可能会使共享自旋锁处于错误状态。 - 如果需要对部分源内存进行分页,
memcpy
可以在内核为您获取内存时阻塞。 - 如果源或目标的一部分内存映射到 I/O,则
memcpy
可能会在内核执行该 I/O 时阻塞(在极端情况下,如内存映射网络文件,memcpy
可能会无限期阻塞(。
内核也可以在复制过程中的任何时候自由交换您的进程,这意味着复制可能需要任意长的时间才能真正完成。
但是,memcpy
不会执行常规内存访问不会执行的任何操作。因此,将其与旋转锁一起使用应该是安全的(无论如何,与正常访问内存一样安全(。
我发现你的问题有些不一致。 我会解释自己。
通常,自旋锁或忙锁会维护正在等待获取锁的进程(或线程(,而不会将 CPU 释放到另一个进程(或线程(这意味着在释放锁时会非常快速地解锁和重新调度机制,但对于长时间的等待时间来说,这是一个非常昂贵的模型......
曾经说过这句话。如果您使用的是旋转锁,原因一定是进程或线程用于检查锁何时释放的循环不应执行超过三到四次,否则 CPU 将浪费一次又一次地检查锁是否已释放。
这完全不鼓励像您要求的那样执行阻塞操作(内存副本通常很奇怪,必须处理不存在的资源---内存页---,但是当它这样做时,您的自旋锁将进入数百万次检查的循环(
自旋锁,旨在保护非常小的内存,其中访问可能意味着最多两次或三次对内存的访问。 在这种情况下,自旋锁将解决问题,因为将线程置于等待状态并重新调度,使用自旋锁将比使用等待/唤醒进程快几百万倍。 但这显然与使用memcpy(3)
功能背道而驰,因为它是一种通用的复制功能,允许一次进行大内存复制。 这意味着资源被锁定在一个线程上的时间可能意味着对另一个线程的数百万次检查(在不同的内核中,因为这是使用旋转锁的另一个原因,当您有一个不同的内核将等待两次或三次访问锁才能看到它解锁时(
在我看来,自旋锁的唯一用途是保护信号量的计数器,或保护对 cond 变量或互斥锁的访问,但绝不用作一般内存副本或大型资源保护。 在这些情况下,最好使用普通的睡眠锁。 如果您打算使用memcpy(3)
我唯一可以假设的是,您在将大量内存复制到其中时使用锁来保护它们。这是更好的处理程序与森帕霍尔或互斥锁。
在现代内核中,进程的唤醒非常高效,以至于用户模式自旋锁几乎无法使用。
作为结论,我的猜测是,您不必考虑使用memcpy()
来保护共享内存区域......但要考虑使用自旋锁本身来做保护。 在大多数情况下,它会损失资源,并使您的系统更重、更慢。