每个进程都可以使用堆内存来存储和共享进程内的数据.每当我们在堆内存中占用一些空间时,我们就有编程规则,我们需要在作业完成后释放它,否则会导致内存泄漏.
int *pIntPtr = new int;
.
.
.
delete pIntPtr;
Run Code Online (Sandbox Code Playgroud)
我的问题:每个进程的堆内存是多少?
如是,
只有当进程处于运行状态时才可能发生内存泄漏.
如果不,
然后它意味着操作系统能够将数据保留在某个内存中.如果是这样,是否有办法通过另一个进程访问此内存.这也可能成为进程间通信的一种方式.
我想回答我的问题是肯定的.请提供宝贵的反馈意见.
我使用openssl_pkcs7_sign和openssl_pkcs7_encrypt创建加密数据.这些函数只接受文件名.我想将临时文件存储在共享内存中以提高性能.我在Linux中可以理解file_put_contents('/dev/shm/xxx', data),但Windows无法实现.PHP中是否有可移植的方式来执行此操作?shmop_功能会有帮助吗?谢谢.
PS:或者有没有办法让这些函数接受数据字符串?
PS2:请不要建议/usr/bin/openssl从PHP 调用.它不便携.
我有一段C++代码来创建共享内存.除非使用JNI,否则可以编写可以读取C++代码创建的内存的Java代码.顺便说一句,我使用的是Windows操作系统.
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 …
我正在为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) 我正在研究共享内存上的Linux内核限制
/proc/sys/kernel/shmall
Run Code Online (Sandbox Code Playgroud)
指定可以分配的最大页面数.将此数字视为x,将页面大小视为p.我假设"x*p"字节是系统范围共享内存的限制.
现在我写了一个小程序来创建一个共享内存段,并且我连接到该共享内存段两次,如下所示
shm_id = shmget(IPC_PRIVATE, 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
exit(1);
}
printf("\n The shared memory created is %d",shm_id);
ptr = shmat(shm_id,NULL,0);
ptr_info = shmat(shm_id,NULL,0);
Run Code Online (Sandbox Code Playgroud)
在上面的程序ptr和ptr_info不同.因此共享内存映射到我的进程地址空间中的2个虚拟地址.
当我这样做时,ipcs它看起来像这样
...
0x00000000 1638416 sun 666 16000000 2
...
Run Code Online (Sandbox Code Playgroud)
现在我的问题已达到上述shmall限制x * p.此限制是否适用于为每个共享内存段分配的所有虚拟内存的总和?或者此限制是否适用于物理内存?
物理内存在这里只是一个(共享内存),当我做2时,上面的程序shmat存在两倍于我的进程地址空间中分配的内存量.如果shmat在单个共享内存段上连续执行,这个限制很快就会出现?
当尝试使用Metal从内存中快速将像素缓冲区绘制到屏幕时,我们创建MTLBuffer对象MTLDevice.makeBuffer(bytesNoCopy:..)以允许GPU直接从内存中读取像素而无需复制它.共享内存实际上是实现良好像素传输性能的必备条件.
问题是makeBuffer需要页面对齐的内存地址和页面对齐length.这些要求不仅在文档中 - 它们也是使用运行时断言强制执行的.
我写的代码必须处理各种传入的分辨率和像素格式,偶尔我会得到未对齐的缓冲区或未对齐的长度.在研究了这个之后,我发现了一个允许我为这些实例使用共享内存的hack.
基本上我所做的是将未对齐的缓冲区地址向下舍入到最近的页面边界,并使用offset参数from makeTexture来确保GPU从正确的位置开始读取.然后我向上舍length入到最近的页面大小.显然内存将是有效的(因为分配只能在页面边界上发生),我认为可以安全地假设GPU没有写入或破坏该内存.
这是我用来从未对齐的缓冲区分配共享缓冲区的代码:
extension MTLDevice {
func makeTextureFromUnalignedBuffer(textureDescriptor : MTLTextureDescriptor, bufferPtr : UnsafeMutableRawPointer, bufferLength : UInt, bytesPerRow : Int) -> MTLTexture? {
var calculatedBufferLength = bufferLength
let pageSize = UInt(getpagesize())
let pageSizeBitmask = UInt(getpagesize()) - 1
let alignedBufferAddr = UnsafeMutableRawPointer(bitPattern: UInt(bitPattern: bufferPtr) & ~pageSizeBitmask)
let offset = UInt(bitPattern: bufferPtr) & pageSizeBitmask
assert(bytesPerRow % 64 == 0 && offset % 64 == 0, …Run Code Online (Sandbox Code Playgroud) 我的火花集群中有一个24核和124Gb ram的节点.当我将spark.executor.memory字段设置为4g,然后广播一个需要3.5gb存储在ram中的变量时,核心是否共同拥有该变量的24个副本?还是一份?
我正在使用pyspark - v1.6.2
是否有可能 - 如果这么谨慎 - 使用sendfile()(或其Darwin/BSD表兄弟fcopyfile())直接在共享内存对象和文件之间传送数据?
像功能sendfile()和fcopyfile()可以执行所有的机械必需品托换数据的这种转移的完全不留内核空间-你沿着两个打开的描述符传,源和目的,调用这些函数时,他们从那里.
复制数据的其他方法总是需要人工操作跨越内核空间和用户空间之间的边界; 这种上下文切换本质上是非常昂贵的,性能方面的.
关于使用共享内存描述符作为参数的主题,我找不到任何确定的东西:没有赞成或反对这种做法的文章; 在各个man页面中没有任何内容; 没有推文公开考虑 - sendfile()共享内存描述符有害; &c ...但是,我认为我应该能够做到这样的事情:
char const* name = "/yo-dogg-i-heard-you-like-shm"; /// only one slash, at zero-index
int len = A_REASONABLE_POWER_OF_TWO; /// valid per shm_open()
int descriptor = shm_open(name, O_RDWR | O_CREAT, 0600);
int destination = open("/tmp/yodogg.block", O_RDWR | O_CREAT, 0644);
void* memory = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, descriptor, 0);
off_t bytescopied = 0;
sendfile(destination, descriptor, &bytescopied, len); …Run Code Online (Sandbox Code Playgroud) 一般容器的写入实现的共享内存/副本(如在Qt容器中找到的那样)被C++ 11移动语义和右值引用所取代?
哪一个失败而另一个成功?或者它们是互补的而不是替代品?
shared-memory ×10
c++ ×6
ipc ×2
windows ×2
apache-spark ×1
atomic ×1
boost ×1
containers ×1
file ×1
heap-memory ×1
ios ×1
java ×1
kernel32 ×1
linux ×1
linux-kernel ×1
memory-leaks ×1
metal ×1
mmap ×1
php ×1
posix ×1
pyspark ×1
python ×1
winapi ×1