Приведенный ниже код отдает предпочтение только первому дочернему элементу, который изменяет общую переменную. Как убрать эту ошибку? - PullRequest
0 голосов
/ 09 февраля 2020

Я хочу записать изменения, сделанные всеми дочерними процессами, в общую переменную с родительским процессом.

Вот проблема. Родительский процесс создает структуру, подобную этой:

struct data
{
        int pid;
        int n;
        char c;
};

Он создает k процессов, и структура разделяется со всеми его дочерними. Переменная c инициализируется значением 'n' и работает как флаг.

Родитель регулярно "просыпается" (из "сна") через случайное количество времени (не более 2 секунд) проверяет значение c, и если c равно 'y', то печатается значение n (вместе с соответствующим pid) и делает c снова равным 'n'.

С другой стороны, каждый ребенок Pi, 1≤ i ≤ k, регулярно "просыпается" (из "сна") через случайное количество времени (не более 2 секунд) проверяет значение c, и если c равен 'n', то присваивает некоторому случайному значению значение n вместе с идентификатором процесса для pid, печатает это значение вместе со своим собственным идентификатором процесса и делает c значением 'y'.

Если выполнение программы прекращается пользователем (нажатием Ctrl- C), родительский элемент со всеми его дочерними элементами должен завершиться, а выделенная память должна быть освобождена.

Вот код:

typedef void (*sighandler_t)(int);
int shmid;

struct data
{
        int pid;
        int n;
        char c;
};

void releaseSHM(int signum)
{
        int status;
        status = shmctl(shmid, IPC_RMID, NULL);
        if (status == 0)
                fprintf(stderr, "Remove shared memory with id = %d.\n", shmid);
        else if (status == -1)
                fprintf(stderr,"Cannot remove shared memory of id = %d.\n", shmid);
        else
                fprintf(stderr, "shmctl() returned wrong value while removing shared memory with id = %d.\n", shmid);



        status = kill(0, SIGKILL);
        exit(signum);
}

int main(int argc, char *argv[])
{
        int num,k=5,i, p1;
        struct data *s;

        sighandler_t shandler;

        shandler =  signal(SIGINT, releaseSHM);

        shmid =  shmget(IPC_PRIVATE, sizeof(struct data), IPC_CREAT | 0777);
        if(shmid==-1)
        {
                perror("shmget() failed");
                exit(1);
        }

        s=(struct data *)shmat(shmid, NULL, 0);
        s->c='n';

        for(i=0;i<k;i++)
        {
                p1=fork();
                if(p1==0)
                {
                        while(1)
                        {
                                //shandler =  signal(SIGINT, releaseSHM);
                                num=(rand()%3);
                                sleep(num);
                                if(s->c=='n')
                                {
                                                s->n=rand();
                                                s->pid=getpid();
                                                printf("Child with pid %d set value of n as %d \n",s->pid,s->n);
                                                s->c='y';
                                }
                                sleep(num);
                        }
                }
                else
                {
                        while(1)
                        {
                                num=(rand()%3);
                                sleep(num);
                                if(s->c=='y')
                                        printf("Parent reads value of n as %d set by child with process id %d \n",s->n, s->pid);
                                s->c='n';
                        }
                }
        }
        return 0;
}

Это дает вывод как:

Child with pid 13883 set value of n as 846930886 
Parent reads value of n as 846930886 set by child with process id 13883 
Child with pid 13883 set value of n as 1957747793 
Parent reads value of n as 1957747793 set by child with process id 13883 
Child with pid 13883 set value of n as 719885386 
Parent reads value of n as 719885386 set by child with process id 13883 
Child with pid 13883 set value of n as 596516649 
Parent reads value of n as 596516649 set by child with process id 13883 
Child with pid 13883 set value of n as 1350490027 
Parent reads value of n as 1350490027 set by child with process id 13883 
^CRemove shared memory with id = 15368197.
Killed

Очевидно, что он фиксирует изменения, сделанные только одним дочерним процессом, и не дает шанса другим дочерним процессам. Как удалить эту ошибку?

Если требуется какая-либо другая информация, оставьте комментарий ниже.

1 Ответ

2 голосов
/ 10 февраля 2020

Вы намереваетесь иметь родителей и k детей, борющихся за общую память, но вместо этого вы порождаете только одного ребенка, независимо от значения k .

You напишите это:

....
for (int i = 0; i < k; i++) {
  pid_t child = fork();
  if (child == 0) do_child_infinite_loop();
  else do_parent_infinite_loop(); // <- BUG: the for loop never resumes
}

Вы хотите сделать это:

....
for (int i = 0; i < k; i++) {
  pid_t child = fork();
  if (child == 0) do_child_infinite_loop();
}
do_parent_infinite_loop();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...