首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IPC共享内存与posix共享内存

IPC共享内存与posix共享内存
EN

Stack Overflow用户
提问于 2014-08-14 13:19:49
回答 1查看 3.2K关注 0票数 3

我目前正在实现一个小型C函数,它使用posix共享内存(shm_open()ftruncate()mmap()shm_unlink() )。

我面临的问题是,我的应用程序正常存在,我的清理例程调用shm_unlink()

但如果我的过程得到kill -9,我面临的问题是,shm部分仍然在那里。我的应用程序使用fork(),甚至可以在几个实例中启动。因此,如果在启动期间我检测到有一个共享内存段,我如何确定它是否是崩溃的剩余物,这样我就可以重置它,或者其他进程可能还在使用它?

在SystemV IPC中,一旦执行了shmget()和后续的shmat(),就有了shm_nattch

是否有类似于posix共享内存的东西?

EN

回答 1

Stack Overflow用户

发布于 2014-08-14 17:14:21

POSIX共享内存实际上是映射内存的一个变体。主要的区别是使用shm_open()打开共享内存对象(而不是调用open()),使用shm_unlink()关闭和删除对象(而不是调用close(),后者不删除对象)。shm_open()中的选项大大少于open()中提供的选项数。

IPC共享内存是在程序之间传递数据的一种有效方法。一个程序将创建一个内存部分,其他进程(如果允许的话)可以访问该部分。

IMHO,它们之间的差别并不大,因为POSIX共享内存只是共享内存概念的后一种和更标准的实现。杀手-9的问题真的是个问题。您不能设置任何处理程序,甚至atexit也不会被调用。但是,您可以为SIGTERM设置处理程序,并使用命令终止进程:

代码语言:javascript
复制
kill -SIGTERM <pid>

atexit和信号处理程序的示例代码:

代码语言:javascript
复制
#include <signal.h>
#include <unistd.h>
#include <cerrno>
#include <system_error>
#include <iostream>

static sigset_t theMask;

static void
signalWrapper(
    int         theSignalNumber,
    siginfo_t*  theSignalDescription,
    void*       theUserContext)
{
  if (theSignalNumber == SIGTERM)
  {
    std::cerr << "Clear shared memory and exit" << std::endl;
    exit(1);
  }

  // Reinstall handler (usefull for other signals)
  struct ::sigaction sa;
  sa.sa_sigaction = &signalWrapper;
  sa.sa_mask = theMask;
  sa.sa_flags = SA_SIGINFO;

  try
  {
    if (::sigaction(theSignalNumber, &sa, NULL) == -1)
      throw std::error_code(errno, std::system_category());
  }
  catch (const std::error_code& ec)
  {
    std::cerr << ec << std::endl;
  }
}

void
setupSignalHandlers()
{
  struct ::sigaction sa;

  // Prepare mask
  sigemptyset(&theMask);
  sigaddset(&theMask, SIGTERM);
  // Add some more if you need it to process

  sa.sa_mask      = theMask;
  sa.sa_flags     = SA_SIGINFO;
  sa.sa_sigaction = &signalWrapper;

  // Perform setup
  try
  {
    if (::sigaction(SIGTERM, &sa, NULL) == -1)
      throw std::error_code(errno, std::system_category());
  }
  catch (const std::error_code& ec)
  {
    std::cerr << ec << std::endl;
  }
}

void
bye()
{
  std::cout << "Bye!" << std::endl;
}

int
main()
{
  std::cout << "Set handler!" << std::endl;
  setupSignalHandlers();
  if (std::atexit(bye))
  {
    std::cerr << "Failed to register atexit" << std::endl;
    return 2;
  }

  std::cout << "Emit SIGTERM signals" << std::endl;
  kill(getpid(), SIGTERM);
  sleep(100);

  return 0;
}

另一种有趣的方法是shm_unlink(),紧随shm_open()和O_CLOEXEC的使用。我编写了小的代码示例来说明unlink和POSIX共享内存重新打开的用法:

代码语言:javascript
复制
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <cerrno>
#include <cstring>

#include <system_error>
#include <iostream>

// Simple ShMem with RAII
struct ShMem
{
  ShMem(
    const std::string& theName)
  : _handle(-1),
    _mode(S_IRUSR | S_IWUSR),
    _name(theName)
  {
    // Here we try to create the object with exclusive right to it
    // If the object exists - it must fail.
    // File opened as 0600. The open mode might be set with
    // class enum and additional paramter to constructor
    if ((_handle = shm_open(_name.c_str(), O_CREAT | O_RDWR | O_EXCL, _mode)) < 0)
    {
      std::cerr << strerror(errno) << std::endl;

      std::cout << "File " << _name << "exists. Try to reopen it!" << std::endl;
      if ((_handle = shm_open(_name.c_str(), O_RDWR | O_TRUNC, _mode)) < 0)
      {
        std::cerr << strerror(errno) << std::endl;
        throw std::error_code(errno, std::system_category());
      }
      else
        std::cout << _name << " reopened OK";
    }
    else
      std::cout << _name << " created OK";

    // Unlink but keep descriptor
    shm_unlink(_name.c_str());
  }

 ~ShMem()
  {
  }

  const int
  handle()
  {
    return _handle;
  }

private:

  int         _handle;
  mode_t      _mode;
  std::string _name;
};

使用O_CLOEXEC,您完全可以删除shm_unlink(),并查看杀害-9上发生了什么。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25309045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档