#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;
}
Вот выходные данные (только последние строки) нажмите на ссылку:
вывод