статические переменные в нескольких процессах (сигналах)

#c #linux #unix #static #fork

#c #linux #unix #статические #форк

Вопрос:

У меня есть 2 процесса, выполняющих test.c. В test.c есть обработчик сигналов, который выполняет execlp. В test.c у меня есть статическая переменная, которую нужно инициализировать только один раз и увеличивать каждый раз перед вызовом execlp. Когда любой из процессов достигает 99, они завершают работу.

К сожалению, прямо сейчас он не увеличивается, я предполагаю, потому что есть 2 процесса, каждый из которых имеет копию статической переменной. Вот test.c:

 #include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

static int i = 0;

static int foo(int j)
{
    printf("In the foo...n");
    j  ;
    printf("%dn", j);
    return j;
}


void main(int argc, char *argv[])
{
    int pid, pid2, k;
    int *h = malloc(sizeof(int));
    int g = 0;
    h = amp;g;

    static char s[15];


    pid = fork();
    if (pid > 0)
    {
        sleep(1);
    }

    if (pid == 0)
    {
        k = foo(*h);

        sprintf(s, "%d", k);
        if (k >= 99)
        {
            printf("k=99n");
            exit(0);        
        }
        execlp("./a.out", "forktest", s, NULL);
    }

    pid2 = fork();

    if (pid2 == 0)
    {

        k = foo(*h);

        sprintf(s, "%d", k);
        if (k >= 99)
        {
            printf("k=99n");
            exit(0);        
        }
        execlp("./a.out", "forktest", s, NULL);

    }

    wait(pid2);
    wait(pid);
}
 

Кто-нибудь может объяснить, почему существует бесконечный цикл? Почему статическая переменная не увеличивается?

Спасибо.

Комментарии:

1. Ваша статическая переменная — это всего i лишь приращения вашего обработчика j , аргумент. Вы пропускаете выделенную память. h .

2. В `int * h = malloc(sizeof(int)); int g = 0; h = amp;g;` malloc — это утечка памяти. Вы вызываете malloc и отбрасываете значение.

3. Я исправил вышеизложенное, но оно по-прежнему не работает. Проблема в exec. Как сказал Радж, нет способа сделать то, что я хочу сделать. Может кто-нибудь предложить способ по-прежнему получать такой счетчик? Спасибо.

Ответ №1:

Здесь используются концепции межпроцессного взаимодействия (канал, fifo, разделяемая память), execlp функция перезаписывает память текущей программы новой программой. Поэтому, когда когда-либо ваш вызов execlp вызывается, ваша программа обновляется и начинается с начала и static int i всегда равна 0.

Я рекомендую использовать pipe Ссылку на это.

Комментарии:

1. Да, это вторая часть присваивания = каналы. Здесь я должен использовать какой-то счетчик без IPC.

Ответ №2:

Вам необходимо использовать проекцию памяти (функцию mmap), если вы хотите использовать концепцию общей памяти между процессами. В вашем коде переменная ‘h’ является общей переменной между тремя процессами.Он должен быть определен с помощью функции mmap и инициализирован в основном процессе, а затем увеличен в двух дочерних процессах.

Ответы на ваши два вопроса связаны: любой из двух дочерних процессов никогда не завершается (exit(0)), потому что if(k> = 99) никогда не статистизируется. Это связано с неразделяемой переменной h, которая не увеличивается.

Я скорее буду использовать цикл while и функцию main возвращаемого типа. Кстати, вам не нужна переменная ‘g’, вы можете инициализировать напрямую ‘h’. И нет необходимости объявлять функцию foo как статическую (статические функции полезны только тогда, когда вы хотите, чтобы они были видны только в файле, в котором они определены). Буфер ‘s’ может быть объявлен нестатическим (это только буфер, который содержит значение k)

Вот модифицированная версия вашего кода, она компилируется и работает нормально.

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

int foo(int* j) 
{   
    printf("In the foo...n");

    (*j)  ;

    printf("%dn", *j);

    return *j;
}

int main(void) 
{
    
    int pid, pid2, k;
    char s[15];
    
    int * h = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    if (h == MAP_FAILED) {
        printf("map failedn");
        return -1;
    }

    *h = 0;
    pid = fork();

    if (pid < 0) {
        printf("fork failed pidn");

        return -1;
    }

    if (pid > 0) {
        sleep(1);
    }
    else {

       while(1) {       
        k = foo(h);

        sprintf(s, "%d", k);

        if (k>=99) {
            printf("k>=99n");
            printf("%sn", s);
            exit(0);

        }

        execlp("./a.out", "forktest", s, NULL);

      }
    }

    pid2 = fork();

    if (pid2 < 0) {
        printf("fork failed pid2n");
    }

    if (pid2 > 0) {
        sleep(1);
    }
    else {
    
       while(1) {   
        k = foo(h);
        
        sprintf(s, "%d", k);

        if (k>=99) {

            printf("k>=99n");

            exit(0);
        }

        execlp("./a.out", "forktest", s, NULL);

        }
    }

    wait(pid);
    wait(pid2);

    return 0;
}
 

Вот выходные данные (только последние строки) нажмите на ссылку:
вывод