【问题标题】:Is there a way to make a function atomic in C?有没有办法在 C 中使函数原子化?
【发布时间】:2009-04-01 07:45:34
【问题描述】:

有没有办法在 C 中使函数成为原子函数。

我不是在寻找可移植的解决方案。(寻找平台 - Win、Linux)

【问题讨论】:

  • 如果您不是在寻找便携式解决方案,则必须指定您的平台

标签: c atomic operations


【解决方案1】:

也许吧。

这完全取决于您对“原子”的定义。

  • 在不涉及操作系统的单核深度嵌入式环境中,您通常可以禁用和启用中断。这可用于允许函数对中断处理程序代码具有原子性。但是,如果您有一个多主总线、一个 DMA 引擎或其他可以独立写入内存的硬件设备,那么在某些情况下,即使屏蔽中断也可能无法提供足够强大的保证。

  • 在 RTOS(实时操作系统)环境中,OS 内核通常提供低级同步原语,例如临界区。临界区是一个代码块,其行为“本质上”是原子的,至少相对于所有其他临界区而言。它通常是操作系统实现其他同步原语的基础。

  • 在多核环境中,通常可以使用称为自旋锁的低级原语。它用于防止进入相对于同一个自旋锁对象的其他用户而言必须是原子的代码块,并通过在一个紧密的循环中阻塞等待的 CPU 内核直到锁被释放(因此得名)来操作。

  • 在许多线程环境中,线程框架提供了更复杂的原语,例如事件、信号量、互斥体和队列。它们与线程调度程序合作,使得等待某事发生的线程在满足条件之前根本不会运行。这些可用于使函数的操作相对于共享同一同步对象的其他线程具有原子性。

一般规则是使用适合任务的环境中可用的最高级别功能。在最好的情况下,可以使用现有的线程安全对象(例如消息队列)来避免在您的代码中执行任何特殊操作。

【讨论】:

    【解决方案2】:

    如果您想确保您的函数不会被信号中断,请使用sigprocmask() 屏蔽和取消屏蔽信号,尽管某些信号无法被阻止(如SIGKILL)和阻止某些信号的行为(如@ 987654323@) 未定义。

    详情请见man sigprocmask

    【讨论】:

      【解决方案3】:

      至少不便携。对于某些系统,您可能可以通过执行诸如关闭机器中断之类的操作来接近它,以防止内核抢占您的功能。但这会非常困难,尤其是对于非嵌入式系统。

      【讨论】:

        【解决方案4】:

        您需要特定平台的支持才能做到这一点 - 通过使用特殊的编译器内在函数来执行硬件指令,或者通过使用操作系统支持。 C 和 C++ 都没有标准化的同步内容。

        【讨论】:

          【解决方案5】:

          定义“原子”的含义。您的意思是“原子”是指在您运行函数时不会选择其他进程或线程进行调度吗?或者您的意思是在您的函数运行时,您的函数中引用的任何共享对象都不会被任何其他线程修改?

          对于前者,您无法从用户空间真正控制它。如果您使用的是单 CPU 计算机,则可以可能通过将进程优先级提高到可能的最高优先级(来自用户空间)来保证原子性。但即使这样也不能保证,因为您的调度算法可能仍然允许另一个进程运行。唯一可靠的方法是通过操作系统。对于单 CPU 机器,您将禁用中断。对于多核机器,您需要锁定总线并等待在其他 CPU 上运行的所有进程被取消。

          这里的问题是:你为什么要保证原子性? 一般来说,只有你的进程可以运行而其他进程不能运行的要求不应该存在于用户空间中。如果你想确保某些数据结构一次只能被一个线程访问,那么你应该使用一个可移植的线程库(例如pthread),并将你的函数作为临界区。

          【讨论】:

            【解决方案6】:

            如果你所说的原子是指“一次只有一个线程”,那么你可以用一个临界区块来保护函数(在 Windows 中)。在 Linux 中,我使用互斥锁/解锁来或多或少地模拟关键部分。

            【讨论】:

              【解决方案7】:

              您可能想研究 POSIX 信号量、互斥锁等,它们可能在 Windows 和 Linux 上都可以使用。

              使用例如cygwin 或 minGW 甚至可以在 Linux 和 Windows 之间编写可移植代码。

              你可以在 Linux 上创建 Windows 库更好:http://cdtdoug.blogspot.com/2009/05/mingw-cross-for-linux.html

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-10-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多