Необъяснимый сегмент общей памяти Linux System V IPC помечен для уничтожения

У меня есть сегмент общей памяти Linux System V IPC, который заполняется одним процессом и читается многими другими. Все процессы используют интерфейс к сегменту разделяемой памяти в форме класса, который заботится о поиске, присоединении и отсоединении сегмента как части своих методов конструктора/деструктора.

Проблема здесь в том, что время от времени я вижу, что сегмент «раскололся». Я имею в виду, что глядя на вывод "ipcs -m -s", я вижу, что у меня есть два перечисленных сегмента: один, который был помечен для уничтожения, но к нему все еще подключены некоторые процессы, и второй, который, как представляется, получить все новые попытки присоединения к сегменту. Однако на самом деле я никогда не прошу ядро ​​уничтожить сегмент. Что тут происходит?!

Еще одна вещь, которую следует отметить, это то, что, к сожалению, система, на которой это работает, серьезно перегружена в отделе памяти. Существует 1 ГБ физической памяти, без подкачки, а Committed_AS в /proc/meminfo сообщает о 2,5 ГБ выделенной памяти. К счастью, системные процессы на самом деле не используют так много памяти ... они просто просят ее (у меня все еще есть около 660 МБ «свободной» памяти, как сообщает vmstat). Хотя я знаю, что это далеко от идеала, в настоящее время я ничего не могу сделать с чрезмерно выделенной памятью. Однако, просматривая исходный код ядра/libc, я не вижу там ничего, что могло бы пометить сегмент общей памяти для удаления по какой-либо причине, кроме запроса пользователя (но, возможно, я где-то пропустил это, спрятанное там).

Для справки здесь конструктор класса интерфейса общей памяти:

const char* shm_ftok_pathname = "/usr/bin";
int shm_ftok_proj_id = 21;

// creates a key from a file path so different processes will get same key
key_t m_shm_key = ftok(shm_ftok_pathname, shm_ftok_proj_id);

if ( m_shm_key  == -1 )
{
    fprintf(stderr,"Couldn't get the key for the shared memory\n%s\n",strerror(errno));
    exit ( status );
}

m_shm_id = shmget(m_shm_key, sizeof(shm_data_s), (IPC_CREAT | 0666));

if (m_shm_id < 0) 
{
    fprintf(stderr,"Couldn't get the shared memory ID\nerrno = %s  \n",strerror(errno));
    exit ( status );
}

// get a ptr to shared memory, which is a shared mem struct 
// second arg of 0 says let OS choose shm address
m_shm_data_ptr = (shm_data_s *)shmat(m_shm_id, 0, 0);

if ( (int)m_shm_data_ptr == -1 )
{
    fprintf(stderr,"Couldn't get the shared memory pointer\n");
    exit ( status );
}

А вот мой вывод uname: Linux 2.6.18-5-686 #1 SMP Пт, 1 июня 00:47:00 UTC 2007 i686 GNU/Linux


person Evan Grim    schedule 19.10.2009    source источник
comment
Интересно, нужно ли вам беспокоиться о убийце Linux OOM из-за нехватки памяти? Погугли это...   -  person Jonathan Leffler    schedule 28.10.2009
comment
Спасибо за вклад, но я не верю, что столкнулся с проблемой OOM. Во-первых, я не вижу никаких признаков убитого процесса, и я не ожидал бы этого, поскольку на самом деле у меня никогда не заканчивается память (т. на самом деле не используя память, есть много доступных страниц). И даже если бы процесс был убит, я не понимаю, как что-либо, что я делаю в настройке общей памяти, может привести к разделению памяти.   -  person Evan Grim    schedule 03.11.2009


Ответы (2)


Мое первое предположение состоит в том, что вы, вероятно, где-то звоните shmctl(..., IPC_RMID, ...).

Можете ли вы показать деструктор класса интерфейса общей памяти?

person Danilo Piazzalunga    schedule 11.01.2010
comment
+1 Согласен, где-то должен быть вызов shmctl(... IPC_RMID,...). Было бы разумно, чтобы это было в деструкторе... Вы уверены, что деструктор не вызывается? - person Steve Lazaridis; 27.01.2010
comment
На самом деле обычно вызывается shmctl(...IPC_RMID...) после первого подключения, поэтому сегмент автоматически удаляется, когда больше не остается ссылок. - person ninjalj; 21.06.2010

Единственная причина, по которой ядро ​​​​помечает сегмент для удаления, - это явный пользовательский вызов. Может быть, вы можете попробовать strace/truss (в Solaris), чтобы узнать, есть ли пользовательский вызов указанной функции, упомянутой в 1 выше. .

Раман Чалотра

person Raman Chalotra    schedule 21.06.2010
comment
На самом деле единственная реальная причина для удаления заключается в том, что сегмент помечен для удаления и не осталось ссылок. - person ninjalj; 21.06.2010