LINUX.ORG.RU

проблемма с shared memory


0

0

Проблемма такого рода. В одной проге создаётся шареная память с 
помощью shm_open, и затем загружается с помощью mmap. Затем в 
полученную область mmap'ом заливаю массив структур. Теперь запускаю 
вторую прогу, так же shm_open и mmap открываю и загружаю шареную 
память. Но весь прикол в том, что в отркрытой памяти находятся 
совершенно другие данные, т.е. не мусор и не нарушенный массив структур, 
а именно кусок конфига шрифтов. Вот и вопрос, почему открылся не тот 
участок памяти?

Тут создаётся память и заливаются данные:

....
	shm_unlink(PB_MEM_DB_FILE);
	if((fmd = shm_open(PB_MEM_DB_FILE,O_RDWR | O_CREAT | O_EXCL, S_IRGRP | S_IWGRP | S_IRUSR | S_IWUSR)) < 0){
			PBWriteToLog("Can't allocate shared memory by shm_open\n");
			exit(1);
	}
	ftruncate(fmd, sizeof(user_mem_unit)*PB_MAX_QUERY_ANSWER / PB_QUERY_STEP);
	users = (user_mem_unit*)mmap(NULL,sizeof(user_mem_unit)*PB_MAX_QUERY_ANSWER / PB_QUERY_STEP,
								PROT_READ | PROT_WRITE, MAP_SHARED, fmd, 0);
....
заливаю данные таким способом
	users[k].nick = strcpy((users[k].nick = new char[strlen(res[i+1])]),res[i+1]);
и.т.д.

А вот так пытаюсь их получить:
...
	struct stat st;

	if((fmd = shm_open(PB_MEM_DB_FILE,O_RDWR,  0)) < 0){
			PBWriteToLog("Can't open shared memory by shm_open\n");
			cout << "Can't open shared memory by shm_open" << endl;
			exit(1);
	}
	fstat(fmd,&st);
	users = (user_mem_unit*)mmap(NULL,st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fmd, 0);

	int i = 0;
	while(i < 100){
		cout << "users[i].nick = " << users[i].nick << endl;
		i++;
	}
...

А вот что выводится:
...
users[i].nick =
users[i].nick = alias>852</alias>
  <alias>cp852</alias>
  <alias>ibm852</alias>
  <collation name="cp852_general_ci"    id="40" flag="primary">
    <order>Hungarian</order>
    <order>Polish</order>
    <order>Romanian</order>
    <order>Croatian</order>
    <order>Slovak</order>
    <order>Slovenian</order>
    <order>Sorbian</order>
  </collation>
  <collation name="cp852_bin"   id="81" order="Binary"  flag="binary"/>
</charset>

<charset name="cp1256">
  <family>Arabic</family>
  <description>Windows Arabic</description>
  <alias>ms-arab</alias>
  <alias>windows-1256</alias>
  <collation name="cp1256_bin"          id="67" order="Binary"  flag="binary"/>
  <collation name="cp1256_generalA
users[i].nick = ary">
    <order>Hungarian</order>
    <order>Polish</order>
...
и так много...

Пробовал вместо shm_open, в читающей проге, open, но результат тот же.
Размер выделяймой области не влияет на результат.

В чём проблемма?

Заранее спасибо!!!
★★★★★
Ответ на: комментарий от romanSA

> А в пишущем процессе вызывал msync(2) или munmap(2) до чтения?

А надо до чтения? Я пробовал после ммапа, но не помогало. Кстати тогда такой вопрос, данные будут автоматически синхронизироваться после того как я их изменю или как?

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

Будут ли данные автоматически синхронизироваться - ещё тот вопрос.
По стандарту для разделяемой памяти должно все работать и без msync() вообще. А вот для файлов msync() необходим.
Так что все зависит от реализации разделяемой памяти POSIX в Linux.
В общем, попробуй сначала msync(), а там может и я примерчик набросаю и посмотрю что к чему.

romanSA
()
Ответ на: комментарий от romanSA

твой код не помещает в шаренную память твои данные (строки) а только указатели на строки находячиеся в адресном пространстве первого процесса за пределами шаренной памяти, следовательно второй процесс читает мусор из своей памяти. странно как у тебя всё это в сегфолт не вылетает

cvv ★★★★★
()
Ответ на: комментарий от romanSA

Еще один вопрос: что за значение у константы PB_MEM_DB_FILE?

romanSA
()
Ответ на: комментарий от romanSA

значение? это просто строка "pbfile"

#define PB_MEM_DB_FILE pbfile

он создаётся в /dev/shm/ т.е. появляется /dev/shm/pbfile

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cvv

> ты хоть сам понял что написал??

дык тоже что и:

users[k].nick = new char[strlen(res[i+1])];
users[k].nick = strcpy(users[k].nick,res[i+1]);

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

и как я могу туда перемещать указатели, когда делаю strcpy?

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

>> ты хоть сам понял что написал??

>дык тоже что и:

>users[k].nick = new char[strlen(res[i+1])];
>users[k].nick = strcpy(users[k].nick,res[i+1]);

ничего ты не понял. мож тебе надо выспатся и ещё раз посмотреть???

cvv ★★★★★
()
Ответ на: комментарий от cvv

cvv совершенно прав:
У тебя сама структура (и поле nick в том числе) хранится в разделяемой памяти, а для данных, на которые указывает .nick ты выделял место в "собственной" памяти процесса, а не в разделяемой памяти.
Самый простой вариант тут, описать поле nick как

struct ... {
...
char nick[MAX_NICK_SIZE];
...
};

и далее просто делать:

strncpy(users[k].nick,res[i+1], MAX_NICK_SIZE - 1);
users[k].nick[MAX_NICK_SIZE - 1]= '\0';

romanSA
()
Ответ на: комментарий от buddha

извиняюсь.

по привычке. я практически всегда пользую memcpy()

cvv ★★★★★
()
Ответ на: комментарий от cvv

>>strncpy(users[k].nick,res[i+1], MAX_NICK_SIZE - 1);
>strncpy(users[k].nick,res[i+1], MIN(MAX_NICK_SIZE,strlen(res[i+1])) -1);

Спасибо за поправку, спешил и не заметил.

romanSA
()
Ответ на: комментарий от romanSA

Опять написал не то: конец рабочего дня понимаете-ли.
Насчет

strncpy(users[k].nick,res[i+1], MIN(MAX_NICK_SIZE,strlen(res[i+1])) -1);

если уж так писать, то нужно
 
strncpy(users[k].nick, res[i+1], 
        MIN(MAX_NICK_SIZE - 1,strlen(res[i+1]) ) );

Иначе не скопировать последний символ из res[]

romanSA
()
Ответ на: комментарий от romanSA

> Будут ли данные автоматически синхронизироваться - ещё тот вопрос.

вопроса нет - будут.

> А вот для файлов msync() необходим.

нет, неправда. msync() нужен только чтобы спровоцировать
запись на диск, если вы боитесь потери данных в случае
краха системы.

idle ★★★★★
()

Вы осторожней с ftruncate: выдержка из man ftruncate гласит "Стандарт POSIX не определяет, что произойдет, если в файле меньшебайт, чем length." - так что для переносимости лучше сделать что-нибудь полинейнее.

no-dashi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.