};
// volatile sig_atomic_t ready = 1;
void signal_handler(int sig)
{
// ready = 1;
}
int main()
{
int pipefd[2];
char buf[max_buf_size];
pid_t pid;
signal(SIGUSR1, signal_handler);
if (pipe(pipefd) == -1) {
fprintf(stderr, "Pipe\n");
exit(1);
}
pid = fork();
if (pid == 0) {
char temp[max_buf_size];
close(pipefd[0]);
while (1) {
// if (ready == 1) {
// printf("Enter message from child(Ctrl+D to stop): ");
// if (fgets(temp, max_buf_size, stdin) == NULL)
// break;
// write(pipefd[1], temp, strlen(temp) + 1);
// ready = 0;
// }
printf("Enter message from child(Ctrl+D to stop): ");
if (fgets(temp, max_buf_size, stdin) == NULL)
break;
write(pipefd[1], temp, strlen(temp) + 1);
pause();
}
exit(0);
}
close(pipefd[1]);
while (read(pipefd[0], buf, max_buf_size) > 0) {
if (buf[0] == '\n') {
kill(pid, SIGTERM);
break;
}
printf("Parent read: %s\n", buf);
kill(pid, SIGUSR1);
}
printf("\n");
return 0;
}
Привет, в общем разбираюсь с дочерними процессами и пайпами, изначально сделал без сигналов и вывод дочернего процесса перекрывал родительский. Сейчас такая реализация, но хотел бы узнать, адекватно сделано или есть лучше подходы?
Если что бейте, но не сильно)
Во-первых, для ликвидации дочернего процесса стоит использовать waitpid. Во-вторых, необходимо обрабатывать исключительные ситуации для read и write. По man pipe вы поймёте, какие коды когда произойдут. В-третьих, нет нужды использовать сигнал для ожидания окончания чтения. В чём тогда смысл двух процессов? Один процесс пишет до тех пор, пока не получит переполнение буфера пайпы, о чем и сообщит и громко упадёт, другой читает, обрабатывает или, если там ошибка, то зависает и происходит переполнение. Короче, сигналы тут конкретно не нужны, как мне кажется. В-четвертых, чтобы завершить работу с пайпом в данной программе, достаточно в родительском процессе читать пока не EOF, а в дочернем просто писать из stdin, пока не EOF(т.е пока не будет нажата комбинация), потом выход из дочернего и в родительском его ликвидация. Наконец, сигнал sigterm для уничтожения использовать не стоит потому, что он просто переводит процесс в другое состояние. У процесса есть 5 состояний: запущен, остановлен, traced, interruptible, uninterrutible. Сигналы переводят его в одно из выше указанных состояний, но не ликвидируют структуру task_struct. Как раз waitpid ждёт изменения состояния и потом очищает ресурс, предотвращая появление т.н процесса zombie.
Ого, спасибо за столь развернутый ответ. Только я не пойму как без сигналов сделать так чтобы сначала родитель прочитал из канала, а только потом продолжить цикл в дочернем. fgets читает либо до \0 либо до \n, вот после \n хочу записывать и выводить в родителе
Это блокирующие операции, поэтому если данных нет, то они просто будут ждать, пока нельзя будет либо что-то прочитать, либо пока не освободиться(или ещё что) дескриптор, куда что-то записывается.
Но вот смотри как получается, как запускаю то выводит: ` Enter message from child(Ctrl+D to stop): тут я пишу что хочу\n Enter message from child(Ctrl+D to stop): Parent read: asasf ` а дальше мне опять даёт возможность ввести
Похоже я просто не выкупил суть задумки. Когда я это писал, то хотел сказать, что нет смысла синхронизировать два процесса, потому что получается почти синхронная программа. Да и по-моему поведение без синхронизации тоже прикольное)
ясно что придумал я какую-то херь и можно это все дело сделать без дочернего процесса, но захотелось таким образом. Если можешь подкинуть более адекватное задание, то буду рад почитать
Обсуждают сегодня