Нужно сделать общим для нескольких процессов массив структур. Решил сделать так: один из процессов выделяет общий блок памяти с помощью shmget
, другие процессы подгружают к себе указатель на этот блок памяти. Когда нужно записать значение в поле элемента массива, делаю так: ((PRUNNING_CONTEXT)(shm + (sizeof(RUNNING_CONTEXT) * i)))->name
, т.е. смещаю указатель в общей области на количество элементов, преобразую к указателю на элемент массива, и обращаюсь к полю. По неизвестной причине при попытке записи/чтения через contextByNum(num)->field
получаю segmentation fault(core dumped)
.
В initContexts
выделяется блок памяти, в него копируется пустой массив с помощью memcpy
, затем с помощью commonSetupContext
выполняется начальная инициализация. В main
вызывается initContexts
, затем выводятся все имена контекстов. Падает в commonSetupContext
при попытке strcpy(pContext->name, getProcessName(num))
. Для интереса пробовал убрать strcpy - падает при обращении к любому полю, как для записи так и для чтения.
//runningContext.h
typedef struct _runningContext {
int num;
int numNextActiveContext;
int active;
int pid;
int ppid;
int pgid;
char name[NAME_SIZE];
int replaceAmount;
int replaceNums[REPLACE_NUMS_SIZE];
int killId;
int killSig;
int killUsr;
int usrRec;
int usr1Rec;
int usr2Rec;
int currRecAmount;
int needRecAmount;
} RUNNING_CONTEXT, *PRUNNING_CONTEXT;
extern RUNNING_CONTEXT contexts[PROCESSES_AMOUNT];
extern int shmKey;
extern int shmId;
extern char* shm;
//runningContext.c
void initContexts() {
shmId = shmget(shmKey, sizeof(contexts), IPC_CREAT | 0666);
if(shmId < 0) {
logerror("Fatal! Can't shmget");
exit(1);
}
shm = shmat(shmId, NULL, 0);
if(shm == (char*)-1) {
logerror("Fatal! Can't shmat");
exit(1);
}
memcpy(shm, contexts, sizeof(contexts));
for(int i = 0; i<PROCESSES_AMOUNT; ++i) {
commonSetupContext(contextByNum(i + 1), i + 1);
}
}
void loadContexts() {
shmId = shmget(shmKey, sizeof(contexts), 0666);
if(shmId < 0) {
logerror("Fatal! Can't shmget");
exit(1);
}
shm = shmat(shmId, NULL, 0);
if(shm == (char*)-1) {
logerror("Fatal! Can't shmat");
exit(1);
}
}
void commonSetupContext(PRUNNING_CONTEXT pContext, int num) {
strcpy(pContext->name, getProcessName(num));
pContext->num = num;
logerror("debug");
pContext->pid = PROCESS_ID_NOT_SET;
pContext->replaceAmount = 0;
pContext->usrRec = 0;
pContext->usr2Rec = 0;
}
PRUNNING_CONTEXT contextByNum(int num) {
if(isNumExists(num) == FALSE) {
logerror("Num not exists, custom error");
return NULL;
}
for(int i = 0; i<PROCESSES_AMOUNT; ++i) {
if(((PRUNNING_CONTEXT)(shm + (sizeof(RUNNING_CONTEXT) * i)))->num == num) {
return (PRUNNING_CONTEXT)(shm + (sizeof(RUNNING_CONTEXT) * i));
}
}
return NULL;
}
//main
initContexts();
for(int i = 0; i<PROCESSES_AMOUNT; ++i) {
logerror("%d. %d", contextByNum(i + 1)->name);
}
При вызове commonSetupContext()
первым параметром идет вызов contextByNum()
, который ищет контекст по номеру ... Но судя по содержимому commonSetupContext
этот самый номер будет установлен им. Следовательно в момент первого вызова contextByNum
номера еще нет в структуре и эта функция возвращает NULL ...
Вообще я бы делал примерно так:
RUNNING_CONTEXT *contexts;
...
shmId = shmget(shmKey, sizeof(RUNNING_CONTEXT)*PROCESSES_AMOUNT, IPC_CREAT | 0666);
...
contexts=(RUNNING_CONTEXT *)shm;
// Вместо (PRUNNING_CONTEXT)(shm + (sizeof(RUNNING_CONTEXT) * i)))->num
contexts[i]->num
И если эти самые num не случайны, а как в вашем примере идут подряд, то их поиск так же не нужен, ибо &contexts[num-1]
уже готовый адрес нужной структуры.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Видел множество вариантов: инстанциация, инстанцирование, инстанцианирование и тп
Хочу запустить свой сервис, написанный на спринге, в докер-контейнереСервис работает с RethinkDB, который уже запущен в контейнере
Пытаюсь решить задачу на Java именно с помощью лямбда выражения