2013-10-12 2 views
4

Я пытаюсь написать оболочку. Когда выполняется процесс переднего плана, конвейер разветвленного процесса получает свой собственный идентификатор группы процессов. Затем терминал передается этому идентификатору группы процессов (с использованием tcsetpgrp), и оболочка ждет его завершения до того, как снова получит управление терминалом. Это прекрасно работает.Проблемы с управлением доступом к терминалу

Проблема возникает, когда я пытаюсь запустить фоновый процесс. Опять же, я передаю всем процессам в конвейере единый идентификатор группы процессов, но на этот раз я не предоставляю управление терминалом этой группе. При запуске вывод заданной фоновой команды выводится на терминал (до того, как он завершен), и терминал возвращает запрос пользователю одновременно. Что должно было произойти, так это то, что дочерний процесс, который пытается записать на терминал, должен получить SIGTTOU, и он должен остановиться, но этого явно не происходит. Я проверил, что все разветвленные процессы имеют одинаковый идентификатор группы процессов и что этот идентификатор отличается от оболочки.

После выхода из оболочки (через ctrl-c) и возврата к стандартной оболочке bash, которая ее запускала, потому что я не воспользовался фоновым процессом после завершения оболочки, фоновый процесс продолжает работать (что исключено). Что странно, так это то, что этот процесс продолжает записывать вывод в оболочку bash, даже если это не процесс переднего плана. Это приводит меня к выводу, что либо этот фоновый процесс не получает никаких SIGTTOU из-за ошибки POSIX (маловероятно), он обрабатывает их (заставляя действие по умолчанию останавливать игнорирование), либо фоновый процесс игнорирует SIGTTOU.

Есть ли способ перед тем, как выполнить процесс раздвоения, убедиться, что он остановится после получения SIGTTOU (при условии, что двоичный код exec ничего не изменит)?

ответ

3

SIGTTOU отправлен на фоновый процесс, который пытается записать на терминал только в том случае, если для этого терминала установлен флаг termios TOSTOP. По умолчанию он обычно не установлен, и в этом случае фоновый процесс может с радостью записать на терминал. (Флаг TOSTOP не влияет чтения разрешений Если процесс пытается читать, он будет послал SIGTTIN.).

Так что, да, есть что-то на первый план процесс можно сделать: использовать tcsetattr установить TOSTOP

+0

Спасибо! Это работает! Для всех, кто интересуется, я включил конкретные ответы в свой ответ. –

1

Решение заключалось в том, чтобы выполнить разветвленный процесс перед вызовом exec:

struct termios term; 
if (tcgetattr(STDIN_FILENO, &term) < 0) 
     printf("ERROR\n"); 
    term.c_lflag = TOSTOP; 
    if (tcsetattr(STDIN_FILENO,TCSANOW,&term)<0) 
     printf("ERROR\n"); 
+0

Я думаю, вы имели в виду | = – rici

+0

Да, спасибо. Еще одна вещь - это предотвращает что-либо, кроме процесса fg, от записи на терминал, но есть ли эквивалент для чтения с терминала? –

+0

Afaik только процесс fg может читать с терминала. Процесс bg может игнорировать SIGTTIN и пытаться читать с терминала, но он не может быть успешным. Поэтому чтение и запись не являются симметричными. – rici

Смежные вопросы