Программа застряла в цикле - PullRequest
0 голосов
/ 08 октября 2019

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

struct shared
{
int count;
sem_t sem;
} *shmem;
void forking()
{
key_t shmkey = ftok("makefile",777);
        if (shmkey == -1) {
            perror("Ftok failed");
            exit(-1);
        }

        // Get our shm id
        shmid = shmget(shmkey, sizeof(shared), 0666 | IPC_CREAT);
        if (shmid == -1) {
            perror("Failed to allocate shared memory region");
            exit(-1);
        }

        // Attach to our shared memory
        shmem = (shared*)shmat(shmid, (void *)0, 0);
        if (shmem == (void *)-1) {
            perror("Failed to attach to shared memory region");
            exit(-1);
        }

    sem_init(&(shmem->sem),1,1);
    pid_t PID;
    int i;
    for(i=0;i<4;i++)
    {
    PID=fork();
    if(PID==0)
    {
        static char *args[]={"./child",NULL};
        int status;
        if(( status= (execv(args[0], args)))==-1)
        perror("failed to execv");
        exit(EXIT_FAILURE);
    }
    if(PID>0)
    {
        while(1)
        {
            sem_wait(&(shmem->sem));
            {
                shmem->count=shmem->count+1;
            }
            sem_post(&(shmem->sem));
        }
    }
    if(PID<0)
    perror("error in fork");
    }
}
main()
{
    forking();
}

в child.c

struct shared
{
int count;
sem_t sem;
} shmem;
void main()
{
    bool alive=true;
    do
    {
    sem_wait(&(shmem->sem));
    if(shmem->count==5)
    {
        shmem->count=0; 
        alive=false;
    }
    sem_post(&(shmem->sem));
    }while(alive);
}

child.c зацикливается бесконечно, не позволяя родительскому элементу увеличивать i до 5. Это происходит, даже если я закомментирую во время цикла в первом файле и простопусть он увеличивается без петель. В конце ничего не выходит.

1 Ответ

1 голос
/ 08 октября 2019

Вы неправильно используете fork и определенно не используете разделяемую память.

Вот несколько моментов

  1. Вызывая fork, вы создаете копию родительского объекта, работающего в другом пространстве памяти. http://man7.org/linux/man-pages/man2/fork.2.html
  2. Используя execve, вы по существу удаляете старую память и заменяете ее новой, которая никак не связана с вашим родительским процессом. http://man7.org/linux/man-pages/man2/execve.2.html

Чтобы ваш код работал, вы должны использовать вместо него pthread_*, так как он будет находиться в том же пространстве памяти и сделает вашу глобальную переменную изменчивой, поскольку gcc попытается оптимизировать ее и будет иметьстранное поведение, если так оно и есть.

Хорошо, похоже, я упустил немало очков, хотя и не совсем ошибался в своих предположениях.

Таким образом, в вашем child.c отсутствует немного кода

  1. Он не содержит всю инициализацию, которую вы сделали в родительском элементе, что необходимо, потому что если вы используете execve вы, по сути, потеряли все сопоставления памяти, которые ранее отображали в родительском процессе.
  2. Ваши родители зацикливаются бесконечно, поэтому shmem->count никогда не будет равным 5, вам придется в какой-то момент сломать или изменить свойусловие в вашем дочернем коде.

Вот как должен выглядеть ваш ребенок.

#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

typedef struct
{
    int count;
    sem_t sem;
} shared;

shared *shmem;
int shmid;
key_t shmkey;

int main()
{
    int alive=1;

    shmkey = ftok("makefile",777);
    if (shmkey == -1) {
        perror("Ftok failed");
        exit(-1);
    }

    // Get our shm id
    shmid = shmget(shmkey, sizeof *shmem, 0);
    if (shmid == -1) {
        perror("Failed to allocate shared memory region");
        exit(-1);
    }

    // Attach to our shared memory
    shmem = (shared*)shmat(shmid, (void *)0, 0);
    if (shmem == (shared *)-1) {
        perror("Failed to attach to shared memory region");
        exit(-1);
    }

    do
    {
        sem_wait(&(shmem->sem));
        printf("%d\n", shmem->count);
        if(shmem->count > 5)
        {
            shmem->count=0; 
            alive=0;
        }
        sem_post(&(shmem->sem));
    }while(alive);

    printf("I have finished %u\n", getpid());
    exit(0);
}
...