【问题标题】:How to tell if it is the first time that a process starts or not如何判断进程是否是第一次启动
【发布时间】:2012-02-19 13:24:14
【问题描述】:

我正在开发一个 C 程序,一些进程需要访问嵌入式 linux 上的共享内存。该共享内存需要在创建时进行初始化。任何附加到此内存的进程都可能崩溃。当它重新启动时(可能是通过 linux INIT),它不能再次初始化共享内存,因为其他进程正在使用它。如何判断创建共享内存的进程的当前启动是第一次还是重新启动。我想出了一个想法,在共享内存中分配一个整数,将其写为 5678956(除 ffffffff 或 00000000 以外的任何数字)之类的数字,以声明该内存已被初始化。但我不确定这是否运作良好,因为关键数据正在存储此内存。任何意见,将不胜感激。谢谢。

【问题讨论】:

    标签: c linux


    【解决方案1】:

    您应该同时使用共享信号量和共享内存段。尝试使用O_EXCL|O_CREAT 和初始值为0 的sem_open 打开信号量。如果成功,创建并初始化共享内存段,然后发布信号量并关闭它。如果以独占模式打开信号量失败,则以非独占方式打开它并等待信号量,然后将其关闭。

    如果您愿意,另一种解决方案:在文件系统中使用带有mmapMAP_SHARED 的命名文件作为共享内存。首先用一个临时名称创建文件,并用它应该包含的初始数据填充它。然后尝试link它的真实姓名。如果linkEEXIST 失败,则您不是第一个进程,您可以删除临时文件并打开并映射现有文件。如果link成功,你就是第一个进程。

    【讨论】:

    • 您甚至可以在tmpfs 文件系统中创建命名文件,这样它就不会触及物理磁盘。
    • 是的,POSIX 指定丑陋的shm_open 接口而不是使用普通文件系统语义定义/dev/shm,这实际上是相当令人沮丧的。无法rename/link 共享内存对象会使它们的用处大大降低。
    • 感谢您的快速回答。您启发我使用 excl|IPC_CREAT 创建共享内存并直接对其进行初始化,而不是使用信号量。到目前为止它工作正常。你知道这是否有任何潜在的问题吗?再次感谢您。
    • 是的,有一个基本的竞争条件,只在共享内存段上使用独占创建。第二个进程可能在第一个进程创建共享内存段之后但在它初始化它的内容之前启动。解决此问题的唯一方法是实现您自己的同步对象(使用原子),其中“零状态”是有效的初始化状态,或者在共享内存之外使用辅助同步对象(如文件系统名称或命名信号量)对象。
    • 感谢 cmets。但我还是有点困惑。我设置的初始化共享内存的条件是只用 EXCL|CREAT 创建共享内存。如果失败,它将仅使用 0666|CREAT 再次 shmget。当第二个进程在第一个创建 shm 之后但在第一个初始化之前启动时,第二个进程如何满足这个条件来初始化共享内存?谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多