Программа состоит из 2 частей (меня попросили использовать трубу):
A. менеджер - который создает процессы, которые помогут ему рассчитать, сколько экземпляров определенного символа находится в файле.
B. Count - Подсчитывает, сколько экземпляров в файле и возвращает канал менеджеру.
Более того, в каждой программе я менял поведение SIGPIPE и менял желаемое поведение.
в менеджере.c:
for(i = 0; i < len_sym; i++){
...
if (pipe(pipe_fds + (2 * i)) == -1) {
perror("ERROR : Failed creating pipe");
exit(EXIT_FAILURE);
}
if ((curr_child = fork()) == 0){ //son
dup2(pipe_fds[2*i + 1], STDOUT_FILENO);
close(pipe_fds[2*i + 1]);
close(pipe_fds[2*i + 0]);
execvp(child_args[0], child_args);
}
else { //parent
if (curr_child == -1){
exit(EXIT_FAILURE);
}
close(pipe_fds[2*i + 1]); // close writerfd
child_pids[i] = curr_child;
printf("%d son created with pid %d\n", i + 1, child_pids[i]);
// if (i == 1) {
// kill(curr_child, SIGPIPE);
// }
}
}
for(i = 0; i < len_sym; i++){
curr_child = waitpid(child_pids[i], &exit_code, 0);
printf("exit code %d\n", exit_code);
printf("child pid %d\n", curr_child);
if (curr_child == -1 || 256 == exit_code) {
exit(EXIT_FAILURE);
}
if (WIFEXITED(exit_code)) {
int bytes_read;
while ((bytes_read = read(pipe_fds[i*2 + 0], buff, BUFF_SIZE)) > 0) {
buff[bytes_read] = '\0';
printf("%s", buff);
}
if (bytes_read == -1) {
perror("ERROR : Failed reading from fifo");
close(pipe_fds[i*2 + 0]);
exit(EXIT_FAILURE);
}
close(pipe_fds[i*2 + 0]);
child_pids[i] = 0;
}
}
обработка SIGPIPE в manager.c
void my_signal_handler(int signum) {
switch (signum) {
case SIGPIPE:
printf("SIGPIPE for Manager process %d. Leaving\n", getpid());
for (int i = 0; i < len_sym; i++) {
if ((child_pids != NULL) && child_pids[i]) {
kill(child_pids[i], SIGTERM);
}
}
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void register_signal_handlin() {
struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = my_signal_handler;
if (0 != sigaction(SIGPIPE, &new_action, NULL)) {
exit(EXIT_FAILURE);
}
}
в счет.с:
for (j = 0; j < file_length; j++){
if (*temp++ == c){
counter++;
}
}
sleep(10);
if (argc > 4){
sprintf(buff, "Process %d finishes. Symbol %c. Instances %d.\n", getpid(), c, counter);
int buff_len = strlen(buff);
int bytes_written;
while ((bytes_written = write(writerfd, p, buff_len)) > 0) {
p += bytes_written;
buff_len -= bytes_written;
}
if (bytes_written == -1) {
perror("PROCESS ERROR : Failed writing to fifo");
close(writerfd);
return EXIT_FAILURE;
}
close(writerfd);
}
обработка SIGPIPE в count.c
void my_signal_handler(int signum) {
switch (signum) {
case SIGPIPE:
printf("SIGPIPE for process %d. Symbol %c. Counter %d.\n", getpid(), c, counter);
exit(EXIT_FAILURE);
case SIGTERM:
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void register_signal_handling() {
struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = my_signal_handler;
if (0 != sigaction(SIGPIPE, &new_action, NULL)) {
exit(EXIT_FAILURE);
}
if (0 != sigaction(SIGTERM, &new_action, NULL)) {
exit(EXIT_FAILURE);
}
}
Таким образом, на самом деле я запускаю программу менеджера и одновременно открываю новый терминал и отправляет kill -13 определенному процессу.
проблемы:
В диспетчере я получаю код выхода 256. Почему?
Флаг WIFSIGNALED не включается, хотя я отправил сигнал процессу.
Возвращение из функции waitpid не -1, а номер процесса, который я отправил kill -13 со второго терминала.
Я пытался отправить kill одному из детей от менеджера, и по какой-то причине он активировал обработчик сигнала менеджера, а не обработчик сигнала ребенка.
Я нахожусь в процессе изучения ОС, поэтому буду рад любой помощи.