В вашем вопросе действительно много всего происходит.
Как написано в ответе @Sigismondo, вы путаете многопоточность с многопроцессорным программированием. У них разные способы связи.
Для упрощения потоки совместно используют одну и ту же память, поэтому поток может видеть, например, значения глобальных переменных, таких как мьютекс семафоров и т. Д.: Если поток изменяет его, это повлияет на другой поток.
В многопроцессорном режиме, когда вы fork()
, новый процесс генерируется с собственным пространством памяти. Сразу после fork()
значения переменных почти одинаковы (кроме pid
, ppid
и т. Д.), Но они находятся в другом пространстве памяти: если у вас есть блок кода, выполняемый только одним процессом, его изменение не будет воздействовать на переменные (семафоры в вашей программе) другого процесса.
В вашем случае: во-первых, если дочерние процессы выполняют одни и те же вещи (т. Е. Генерируют случайное число), зачем вам разные функции? Разве вы не можете сделать что-то вроде:
#include<stdlib.h>
int generateRand()
{
n = rand() % 100 + 1; //should be random in [1, 100]
}
СИГНАЛЫ ОБРАБОТКИ
Процесс P1 должен обрабатывать сигнал прерывания SIGINT. В частности, на
При поступлении этого сигнала P1 должно отображаться предупреждающее сообщение «P1
Процесс занят! ". Программа завершается родительским процессом P, когда
он проверяет, что сумма чисел, которые он получил от
дочерний процесс, принимает значение 100.
Это действительно неясно, по моему мнению. Родитель должен поймать сигнал SIGINT
. Что должны делать дети? Из того, что вы говорите, кажется, что они не должны поймать этот сигнал. В этом случае вы должны взглянуть на маски сигналов: в основном вы должны заблокировать сигнал в родительском элементе, вызвать fork()
s и затем вернуть исходную маску. Теперь вы должны пойти глубже, но что-то вроде этого ( здесь )
sigset_t *parent_mask, *child_mask
//get the current mask
if (int res = sigprocmask (0, NULL, child_mask)<0)
printf("some error\n");
//make the mask block the signal
if (int res = sigaddset(child_mask, SIGINT)<0)
printf("some error in sigaddset \n");
// block the signal with the new mask
if (int res = sigprocmask (SIG_SETMASK, child_mask, parent_mask)<0)
printf("some error\n");
//do your forks: children will inherit the current mask and will not catch SIGINT
...
fork()
...
fork()
....
//set back the original mask so the parent catches SIGINT
if (int res = sigprocmask (SIG_SETMASK, parent_mask, NULL)<0)
printf("some error\n");
Это мой ответ , хотя для многопоточности должно быть немного понятнее.
ОБРАБОТКА СИГНАЛА
Почему вы регистрируете обработчик сигнала в codeprocess1(int pd[])
? Я совсем не понимаю. И почему SIGUSR1
?
Вы должны сделать это в родительском (до или после fork()
s не должно меняться, так как сигнал заблокирован для детей: это зависит от того, хотите ли вы, чтобы пользователь вышел из программы перед запуском forks()
или нет: в первом случае зарегистрируйте обработчик сигнала после fork()
, в противном случае поместите его в начало main()
. В обоих случаях вы должны сделать:
signal(SIGINT, handler);
Теперь ядро вашей программы: для сообщения вашей программы вы можете использовать pipe()
блокирующим образом вместе с файловыми дескрипторами: отметьте здесь .
Вам нужны два файловых дескриптора (по одному на дочерний процесс и закрытие конца (чтение / запись), не используемого процессом).
Рассмотрим один дочерний процесс:
int p = fork();
int fd1[2]; //file descriptor for child1
int fd2[2]; //file descriptor for child2
if (p>0)//parent
{
close(fd1[1]);//close writing end
int n;
read(fd1[0], &n, sizeof(n));
//you might to call the other fork here and redo the same stuff
int p2 = fork();
if (p2>0)
{
close(fd2[1]);//close writing end
int n2;
read(fd2[0], &n2, sizeof(n2));
sum = n2+n1
if (sum==100 && exit = 1)
{
kill(p, SIGKILL);
kill(p2, SIGKILL);
}
}
}
else if(p==0)//child
{
close(fd1[0]);//close read end
int rand_n = generateRand();//or whaterver the name
wrote(fd1[1], &rand_n, sizeof(rand_n));
}
Условие выхода зависит как от значения суммы (100), так и от того, что были нажаты CTRL + C. Первое очевидно в коде выше. Для последнего вы можете объявить глобальную переменную (я использовал exit
), что если 0 CTRL + C не была нажата, если 1 она была нажата. Это значение проверяется в условии выхода из кода выше. Ваш обработчик должен будет написать эту переменную:
//global variable here
int exit = 0;
void handler(int signo)
{
print("Parent busy doing stuff\n");
exit =1;
}
Заметьте, что одна вещь exit
написана родителем, поскольку она написана ТОЛЬКО в обработчике, который вызывается только родителем, и читается в части кода, выполняемой только родителем: дети читают ее значение всегда будет 0 для них.
Поскольку ваш вопрос слишком общий, я попытался дать некоторые подсказки: в моем коде могут быть ошибки, поскольку я не пробовал. Вы должны учиться самостоятельно. Если вы приведете минимальный рабочий пример, я постараюсь помочь.