两个Windows进程的内存映射了相同的共享文件.如果文件由计数器组成,是否适合使用Interlocked*函数(如InterlockedIncrement)来更新这些计数器?那些会跨进程同步访问吗?或者我需要使用更重的东西,比如互斥体?或者共享内存机制本身也可以确保一致的视图.
我正在开发一种机制,用于在Linux上使用共享内存在两个或多个进程之间交换数据.问题是需要一定程度的并发控制来维护共享内存本身的数据完整性,而且由于我的某些时刻我的进程可能被杀死/崩溃,常见的锁机制不起作用,因为它们可能会留下内存处于"锁定"状态并在死亡后立即使其他进程挂起等待锁被释放.
因此,做了一些研究我发现System V信号量有一个名为SEM_UNDO的标志,它可以在程序失败时恢复锁定状态,但这并不能保证工作.另一种选择是从可能使用共享内存的所有进程监视PID,并在发生了令人讨厌的事情时对它们进行一些控制,但我不确定这是否是解决我的问题的正确方法.
有任何想法吗??:)
编辑:为了便于说明,我们的应用程序需要某种具有最小延迟的IPC机制.所以,我对可以处理这个要求的机制持开放态度.
我正在尝试从Java连接到本地数据库(SQL Server 2008).我已根据客户要求禁用了tcp连接,但我无法连接.我必须禁用服务SQL Server Browser.
我用Java编写下一个语句:
conexion = DriverManager.getConnection("jdbc:sqlserver://localhost\\SQLEXPRESS;user=user;password=password");
Run Code Online (Sandbox Code Playgroud)
我有以下错误:
"java.net.SocketTimeoutException:接收超时".(然后它告诉我可能有防火墙,我应该运行SQL Server浏览器).
如果我尝试从Microsoft SQL Server Managment Studio连接,我可以连接相同的参数:
Server type: Database Engine
Server name: localhost\SQLEXPRESS
Authentication: SQL Server Authentication
User: user
Password: password
Run Code Online (Sandbox Code Playgroud)
我不知道我是不是做错了我的Java但SQL Server Managment Studio实际上是一个客户端,所以如果它可以连接任何客户端应该可以.
请回答.如果您需要更多信息,请直接询问.
我在放入boost::lockfree::queue<<T, fixed_sized<false>, ..>
共享内存时遇到问题.我需要它,因为我必须能够将超过65535条消息插入队列,并且fixed_sized队列限制为65535.
以下代码正常工作(但capacity<...>选项暗示fixed_sized<true>):
typedef boost::interprocess::allocator<
MessageT,
boost::interprocess::managed_shared_memory::segment_manager>
ShmemAllocator;
typedef boost::lockfree::queue<
MessageT,
boost::lockfree::capacity<65535>,
boost::lockfree::allocator<ShmemAllocator> >
Queue;
m_segment = new boost::interprocess::managed_shared_memory(
boost::interprocess::create_only, segmentName, size);
Queue* m_queue = m_segment->construct<Queue>(
queueName)(
m_segment->get_segment_manager());
...
m_queue->bounded_push(message);
Run Code Online (Sandbox Code Playgroud)
以下代码也正常工作(但它不使用共享内存):
boost::lockfree::queue<MessageT> q;
....
q.bounded_push(message);
Run Code Online (Sandbox Code Playgroud)
但是当我尝试将它结合起来时:
typedef boost::interprocess::allocator<
MessageT,
boost::interprocess::managed_shared_memory::segment_manager>
ShmemAllocator;
typedef boost::lockfree::queue<
MessageT,
boost::lockfree::allocator<ShmemAllocator> >
Queue;
m_segment = new boost::interprocess::managed_shared_memory(
boost::interprocess::create_only, segmentName, size);
Queue* m_queue = m_segment->construct<Queue>(
queueName)(
m_segment->get_segment_manager());
...
m_queue->bounded_push(message);
Run Code Online (Sandbox Code Playgroud)
它无法使用以下日志进行编译:
In file included from src/model/Queue.h:16:
In file included from /home/uppi/lib/include/boost/lockfree/queue.hpp:24: …Run Code Online (Sandbox Code Playgroud) 我不知道如何去做,因为我已经看到了用于进程间通信的共享内存的例子.我想知道我是否可以从服务器中利用它来获取某些对象的定期快照,并以某种格式将它们转储到共享内存中...如果我的程序崩溃了......可以在重新启动程序时检索复苏.这可行吗?如果是这样,我可以看一下如何开始?
更新:我在某处看到Linux上的共享内存(我在linux上)是持久性的,所以我想我可能能够定期保存状态快照而无需辅助进程.比方说,一个不断更新的结构,我每隔几秒就转储到共享内存.我选择共享内存而不是文件的原因纯粹是为了速度,因为状态会是很多二进制数据.
Boost提供了一个原子引用计数共享指针的示例
以下是相关的代码段以及所使用的各种排序的说明:
class X {
public:
typedef boost::intrusive_ptr<X> pointer;
X() : refcount_(0) {}
private:
mutable boost::atomic<int> refcount_;
friend void intrusive_ptr_add_ref(const X * x)
{
x->refcount_.fetch_add(1, boost::memory_order_relaxed);
}
friend void intrusive_ptr_release(const X * x)
{
if (x->refcount_.fetch_sub(1, boost::memory_order_release) == 1) {
boost::atomic_thread_fence(boost::memory_order_acquire);
delete x;
}
}
};
Run Code Online (Sandbox Code Playgroud)
使用memory_order_relaxed可以始终增加引用计数器:对象的新引用只能从现有引用形成,并且将现有引用从一个线程传递到另一个线程必须已经提供任何所需的同步.
在删除不同线程中的对象之前,必须在一个线程(通过现有引用)中强制执行对对象的任何可能访问.这是通过在删除引用之后的"释放"操作(通过此引用对对象的任何访问必须明显发生之前)和在删除对象之前的"获取"操作来实现的.
可以将memory_order_acq_rel用于fetch_sub操作,但是当引用计数器尚未达到零时,这会导致不需要的"获取"操作,并且可能会造成性能损失.
我无法理解为什么memory_order_acquire屏障在之前是必要的delete x手术.具体来说,如何在不违反单线程语义的情况下对编译器/处理器重新排序和测试值delete x之前的内存操作是否安全?fetch_subx == 1
编辑我想,我的问题不是很清楚.这是一个改写版本:
读取x(x->refcount_.fetch_sub(1, boost::memory_order_release) == 1)和delete x操作之间的控制依赖性是否会提供任何排序保证?即使考虑单线程程序,编译器/处理器是否可以重新排序与delete x之前的操作相对应的指令fetch_sub …
我的任务是创建两个不同的C文件,然后使用信号量进行进程同步(我同时运行两个C文件).
我主要担心的是:如果我想在两个进程中访问信号量(C文件的可执行文件),我需要在共享内存中创建信号量.我还需要创建二进制信号量.
因为这是我的第一个程序,有人可以建议如何开始这个吗?
我能够创建和使用共享内存,在线程中使用信号量.我在YouTube上看了一些讲座,但找不到合适的解决方案.
我正在为Windows7编写一些内核端代码来访问在用户模式下创建的共享内存,如此处所示.
共享内存在用户空间中创建,名称为:
"MySharedMem"
Run Code Online (Sandbox Code Playgroud)
在用户空间中打开共享内存有效.
在内核模式下打开相同的共享内存调用 ZwOpenSection失败返回:
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
Run Code Online (Sandbox Code Playgroud)
内核代码是:
NTSTATUS CModule1::OpenShared()
{
SIZE_T vs = 256;
WCHAR stringBuffer[] = L"\\BaseNamedObjects\\MySharedMem";
UNICODE_STRING sectionName;
RtlInitUnicodeString(§ionName,stringBuffer);
OBJECT_ATTRIBUTES myAttributes;
InitializeObjectAttributes(&myAttributes,§ionName,0,NULL,NULL);
NTSTATUS status0 = ZwOpenSection(§ionHandle_,SECTION_MAP_READ|SECTION_MAP_WRITE,&myAttributes);
NTSTATUS status = ZwMapViewOfSection(§ionHandle_, ZwCurrentProcess(), (PVOID *)&pSharedData_, 0, 0, NULL, &vs, ViewShare, 0, PAGE_READWRITE);
return status;
}
Run Code Online (Sandbox Code Playgroud)
我尝试了几个名字(L"\\MySharedMem"或L"MySharedMem"),但我得到了其他错误STATUS_OBJECT_PATH_INVALID或STATUS_OBJECT_PATH_NOT_FOUND.
同时创建共享内存"Global\\MySharedMem"不起作用.
我究竟做错了什么?
我尝试在内核模式下创建共享内存,我获得了成功ZwCreateSection,ZwMapViewOfSection但是当我访问pSharedData_指针来测试缓冲区时,我得到了访问冲突:
NTSTATUS CModule1::MapUserSection()
{
typedef struct SHARED_SECTION {DWORD i; };
NTSTATUS status …Run Code Online (Sandbox Code Playgroud) 与此类似帖子,我想创建一个名为共享内存段(通过创建shm_open()+ mmap()特定的NUMA节点(不一定是本地)上的CentOS 7).该帖子建议通过使用来实现numa_move_pages().
我还有几个问题:
如果另一个进程(在不同NUMA的本地核心上运行)稍后启动并且mmap()s到同一个命名的共享内存段,OS是否会决定将命名的共享内存段移动到此进程的本地NUMA?如果是,我该如何预防呢?
是否还有其他情况,在我指定后,命名共享内存段将被移动到另一个NUMA numa_move_pages()?
给定一个命名的共享内存段/shm/dev,如何检查它属于哪个NUMA节点?
我查看了numactl,它的--membind选项是我想要的,但我不确定如果两个不同的进程使用--membind2个不同的节点会产生什么影响.谁赢?如果#3得到解答,我想我可以测试一下.
谢谢!
shared-memory ×10
c++ ×4
c ×3
linux ×3
boost ×2
winapi ×2
atomic ×1
fork ×1
interlocked ×1
interprocess ×1
ipc ×1
jdbc ×1
kernel32 ×1
large-data ×1
lock-free ×1
locking ×1
numactl ×1
numpy ×1
posix ×1
python ×1
semaphore ×1
sql ×1
sql-server ×1
windows ×1