gpt4 book ai didi

linux - 共享内存的限制如何在 Linux 上工作

转载 作者:IT王子 更新时间:2023-10-29 00:14:49 25 4
gpt4 key购买 nike

我正在研究 Linux 内核对共享内存的限制

/proc/sys/kernel/shmall

指定可以分配的最大页数。将此数字视为 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);

在上面的程序中,ptrptr_info 是不同的。所以共享内存被映射到我的进程地址空间中的 2 个虚拟地址。

当我执行 ipcs 时,它看起来像这样

...
0x00000000 1638416 sun 666 16000000 2
...

现在来到上面我的问题中提到的 shmall 限制 x * p。此限制是否适用于为每个共享内存段分配的所有虚拟内存的总和?还是此限制适用于物理内存?

物理内存在这里只有一个(共享内存),从上面的程序中,当我执行 2 个 shmat 时,我的进程地址空间中分配的内存量是原来的两倍。因此,如果在单个共享内存段上连续执行 shmat,这个限制很快就会达到?

最佳答案

该限制仅适用于物理内存,即为所有段分配的实际共享内存,因为 shmat() 只是将分配的段映射到进程地址空间。

你可以在内核中追踪它,只有一个地方检查了这个限制——在 newseg() function 中。分配新段(ns->shm_ctlall 比较)。 shmat() implementation忙于很多事情,但根本不关心 shmall 限制,所以你可以根据需要多次映射一个段(好吧,地址空间也是有限的,但实际上你很少关心这个限制).

您也可以使用像这样的简单程序从用户空间尝试一些测试:

#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

unsigned long int get_shmall() {
FILE *f = NULL;
char buf[512];
unsigned long int value = 0;

if ((f = fopen("/proc/sys/kernel/shmall", "r")) != NULL) {
if (fgets(buf, sizeof(buf), f) != NULL)
value = strtoul(buf, NULL, 10); // no proper checks
fclose(f); // no return value check
}
return value;
}

int set_shmall(unsigned long int value) {
FILE *f = NULL;
char buf[512];
int retval = 0;

if ((f = fopen("/proc/sys/kernel/shmall", "w")) != NULL) {
if (snprintf(buf, sizeof(buf), "%lu\n", value) >= sizeof(buf) ||
fwrite(buf, 1, strlen(buf), f) != strlen(buf))
retval = -1;
fclose(f); // fingers crossed
} else
retval = -1;
return retval;
}

int main()
{
int shm_id1 = -1, shm_id2 = -1;
unsigned long int shmall = 0, shmused, newshmall;
void *ptr1, *ptr2;
struct shm_info shminf;

if ((shmall = get_shmall()) == 0) {
printf("can't get shmall\n");
goto out;
}
printf("original shmall: %lu pages\n", shmall);
if (shmctl(0, SHM_INFO, (struct shmid_ds *)&shminf) < 0) {
printf("can't get SHM_INFO\n");
goto out;
}
shmused = shminf.shm_tot * getpagesize();
printf("shmused: %lu pages (%lu bytes)\n", shminf.shm_tot, shmused);
newshmall = shminf.shm_tot + 1;
if (set_shmall(newshmall) != 0) {
printf("can't set shmall\n");
goto out;
}
if (get_shmall() != newshmall) {
printf("something went wrong with shmall setting\n");
goto out;
}
printf("new shmall: %lu pages (%lu bytes)\n", newshmall, newshmall * getpagesize());
printf("shmget() for %u bytes: ", (unsigned int) getpagesize());
shm_id1 = shmget(IPC_PRIVATE, (size_t)getpagesize(), IPC_CREAT | 0666);
if (shm_id1 < 0) {
printf("failed: %s\n", strerror(errno));
goto out;
}
printf("ok\nshmat 1: ");
ptr1 = shmat(shm_id1, NULL, 0);
if (ptr1 == 0) {
printf("failed\n");
goto out;
}
printf("ok\nshmat 2: ");
ptr2 = shmat(shm_id1, NULL, 0);
if (ptr2 == 0) {
printf("failed\n");
goto out;
}
printf("ok\n");
if (ptr1 == ptr2) {
printf("ptr1 and ptr2 are the same with shm_id1\n");
goto out;
}
printf("shmget() for %u bytes: ", (unsigned int) getpagesize());
shm_id2 = shmget(IPC_PRIVATE, (size_t)getpagesize(), IPC_CREAT | 0666);
if (shm_id2 < 0)
printf("failed: %s\n", strerror(errno));
else
printf("ok, although it's wrong\n");
out:
if (shmall != 0 && set_shmall(shmall) != 0)
printf("failed to restrore shmall\n");

if (shm_id1 >= 0 && shmctl(shm_id1, IPC_RMID, NULL) < 0)
printf("failed to remove shm_id1\n");

if (shm_id2 >= 0 && shmctl(shm_id2, IPC_RMID, NULL) < 0)
printf("failed to remove shm_id2\n");

return 0;
}

它所做的是将 shmall 限制设置为仅比系统当前使用的页面高出一页,然后尝试获取页面大小的新段并将其映射两次(全部成功),然后试图再获取一个页面大小的段,但失败了(以 super 用户身份执行程序,因为它写入 /proc/sys/kernel/shmall):

$ sudo ./a.out 
original shmall: 18446744073708503040 pages
shmused: 21053 pages (86233088 bytes)
new shmall: 21054 pages (86237184 bytes)
shmget() for 4096 bytes: ok
shmat 1: ok
shmat 2: ok
shmget() for 4096 bytes: failed: No space left on device

关于linux - 共享内存的限制如何在 Linux 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37195896/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com