使用shmat命令在C中使用共享内存“无法分配内存”问题

时间:2022-06-01 18:43:08

I have two programs in C that need to communicate with each other. There is a single variable that I am storing in shared memory using shmget(key, 27, IPC_CREAT | 0666) in one program. I update this variable every 1 second. From the other program, I access it every 1 second using shmget(key, 27, 0666).

我在C中有两个需要相互通信的程序。我在一个程序中使用shmget(key,27,IPC_CREAT | 0666)存储在共享内存中的单个变量。我每1秒更新一次这个变量。从另一个程序,我使用shmget(key,27,0666)每1秒访问一次。

This works great, but after a while (usually a few hours), the program that retrieves the data crashes with a segfault. I used gdb to pinpoint the seg fault to the shmget(key, 27, 0666) line. The error code returned is:

这很好用,但过了一段时间(通常是几个小时),检索数据的程序会发生段错误。我使用gdb将seg故障定位到shmget(key,27,0666)行。返回的错误代码是:

ENOMEM Could not allocate memory for the descriptor or for the page tables.

ENOMEM无法为描述符或页表分配内存。

When I check the shared memory segments from the command prompt using ipcs -m, I currently see this:

当我使用ipcs -m从命令提示符检查共享内存段时,我目前看到:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 65536      root       600        393216     2          dest         
0x00000000 98305      root       600        393216     2          dest         
0x00000000 131074     root       600        393216     2          dest         
0x00000000 163843     root       600        393216     2          dest         
0x00000000 196612     root       600        393216     2          dest         
0x00000000 229381     root       600        393216     2          dest         
0x00000000 262150     root       600        393216     2          dest         
0x00000000 294919     root       600        393216     2          dest         
0x00000000 327688     root       600        393216     2          dest         
0x00000000 589833     root       600        393216     2          dest         
0x00000000 655370     root       600        393216     2          dest         
0x00000000 524299     root       600        393216     2          dest         
0x00000000 688140     root       666        27         0                       
0x0008aa53 720909     root       666        27         31950                   
0x0006f855 753678     root       666        27         33564                   

It seems to me like there's an issue with the shared memory I'm using hitting some kind of maximum? But I'm not sure what to do about that, and I'm finding precious little info by google searching. Any thoughts? This program needs to run for ~24 hours at a time at least, if not longer.

在我看来,我使用的共享内存存在问题,达到某种最大值?但我不知道该怎么做,而且我通过谷歌搜索找到了宝贵的小信息。有什么想法吗?该程序至少需要运行约24小时,如果不是更长时间。

Thank you in advance.

先谢谢你。

1 个解决方案

#1


2  

You seem to misunderstand how to use Sys V shared memory segments. You should not need to perform a shmget() more than once in the same process for the same shared memory segment. You are meant to get a segment ID via shmget(), attach it to your memory space via shmat(), and thereafter simply read and/or write it as many times as you want. Modifications will be visible to other processes that have attached the same shared memory segment.

您似乎误解了如何使用Sys V共享内存段。您不需要在相同的共享内存段的同一进程中多次执行shmget()。您应该通过shmget()获取段ID,通过shmat()将其附加到您的内存空间,然后根据需要多次读取和/或写入它。对于已附加相同共享内存段的其他进程,可以看到修改。

If you nevertheless do attach the memory segment multiple times, then you must be sure to also detach it each time via shmdt(), else, yes, you will eventually fill up the process's whole address space.

如果你仍然多次附加内存段,那么你必须确保每次都通过shmdt()分离它,否则,是的,你最终会填满进程的整个地址空间。

In addition, to use shared memory properly, you need some kind of synchronization mechanism. For this purpose, the natural complement to Sys V shared memory segments is Sys V semaphores. You use this to prevent one process from reading while another process is writing the same data.

另外,要正确使用共享内存,需要某种同步机制。为此,Sys V共享内存段的自然补充是Sys V信号量。您可以使用它来防止一个进程读取而另一个进程正在写入相同的数据。

#1


2  

You seem to misunderstand how to use Sys V shared memory segments. You should not need to perform a shmget() more than once in the same process for the same shared memory segment. You are meant to get a segment ID via shmget(), attach it to your memory space via shmat(), and thereafter simply read and/or write it as many times as you want. Modifications will be visible to other processes that have attached the same shared memory segment.

您似乎误解了如何使用Sys V共享内存段。您不需要在相同的共享内存段的同一进程中多次执行shmget()。您应该通过shmget()获取段ID,通过shmat()将其附加到您的内存空间,然后根据需要多次读取和/或写入它。对于已附加相同共享内存段的其他进程,可以看到修改。

If you nevertheless do attach the memory segment multiple times, then you must be sure to also detach it each time via shmdt(), else, yes, you will eventually fill up the process's whole address space.

如果你仍然多次附加内存段,那么你必须确保每次都通过shmdt()分离它,否则,是的,你最终会填满进程的整个地址空间。

In addition, to use shared memory properly, you need some kind of synchronization mechanism. For this purpose, the natural complement to Sys V shared memory segments is Sys V semaphores. You use this to prevent one process from reading while another process is writing the same data.

另外,要正确使用共享内存,需要某种同步机制。为此,Sys V共享内存段的自然补充是Sys V信号量。您可以使用它来防止一个进程读取而另一个进程正在写入相同的数据。