| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Программирование под Unix/Linux > Обработка сигналов в Bash |
| Автор: savigm 26.3.2009, 19:03 |
| Добрый день. Есть скрипт на bash запускающий программу, не соодержащую обработчика сигналов. По запуску скрипта, во время выполнения программы, если нажать [CTRL]+[C] - на экран вылезет ^C. Одно из двух - либо bash отображает введенный символ, либо ядро обрабатывая сигнал и выдает на терминал ^C. Поясните поподробней от кого идет выдача и как этого избажать(перенаправление вввода-вывода не помогает). |
| Автор: MAKCim 26.3.2009, 23:20 |
| я так понимаю речь идет про GUI эмулятор терминала типа gnome-terminal и Konsole обычно с GUI эмуляторами терминалов связываются программы-интерпретаторы (bash, csh, zsh и т. д) говоря простым языком это то, что мы прописываем в конфиге (или в другом месте) GUI программы и что запускается при ее старте если углубиться в детали, то происходит следующее 1. при запуске GUI эмулятора он через open() открывает /dev/ptmx реализация обработчика open для /dev/ptmx создает псевдотерминальное устройство, состоящее из master и slave компонентов доступ к master компоненту имеет только процесс GUI эмулятора (open() возвращает ему соответствующий дескриптор) slave компонент доступен любому процессу через виртуальную ФС /dev/pts (в процессе работы обработчика open slave компонент отображается на /dev/pts в виде файла символьного устройства 0, 1, 2, ..., который можно открыть) 2. GUI эмулятор порождает процесс и запускает в нем соответствующий ему интерпретатор через execve() перед вызовом execve() он перенаправляет стандартный ввод-вывод порожденного процесса на /dev/pts/X, где X - символьное устройство, соответствующее slave компоненту псевдотерминального устройства все, связь готова 3. GUI эмулятор связан через gtk[+]/qt с Xlib API, через который он взаимодействует с X сервером и в частности получает события от клавиатуры при наборе текста (это могут быть скан-коды или что-то другое) на этом уровне различные комбинации типа ^C представляют собой просто последовательность байт 4. вся последовательность байт as is записывается в master компонент через write() на дескрипторе вот тут начинаетс шаманство ;) из буфера master компонента последовательность байт передается в slave компонент, где идет ее преобразование в соответствие с настройками slave компонента настроить можно через ioctl или tc* обертки на дескрипторе, полученном через open() на /dev/pts/X здесь как раз можно связать управляющую комбинацию ^C и генерацию сигнала т. е slave компонент при парсинге последовательности байт может сгенерировать сигнал для всех процессов из foreground группы, которые используют /dev/pts/X в виде дескриптора bash всегда перехватывает SIGINT (маппинг ^C) и записывает символьную последовательность "^C" на стандартный поток вывода, который, как я отмечал выше, связан со slave компонентом. Эта последовательность байт без изменений копируется в приемный буфер master компонента дальше GUI эмулятор может прочесть эти данные через read() на своем дескрипторе и вывести их через Xlib API на экран |
| Автор: savigm 27.3.2009, 01:37 |
| Ok, тогда как обьяснить аналогичное явление в виртуальной консоли (не терминале): в login (это еще не bash) нажатие [Ctrl]+[C] также приводит к отображению ^C? Во время работы программы ввод-вывод если я не ошибаюсь идет уже не с bash, а с программой. Как все-таки этого избежать? Есть прогамка с обработчиком сигнала SIGINT, так она нормально завершается ничего не отображая. Получается сей эффект проявляется только если в программе не установлен обработчик сигнала? Кроме того: если посылать kill -2 <PID>, никакого ^C нет. Т.е. это следствие нажатия клавиш, а не сигнала как такового, однако наличие обработчика решает проблему. |
| Автор: savigm 27.3.2009, 13:06 | ||||||
Slave компонент насколько я понимаю связан с bash? Если в терминале у меня запущена программа весь ввод и вывод идет на нее по схеме Клавиатура/Монитор<->Терминал<->Bash<->Программа? Т.е. весь клавиатурный ввод серва парсится bash'ом, потом отправляется на /dev/ptsx? Что значит "для всех процессов из foreground группы", разве foreground - это не единственная программа запущенная в bash и занимающая ввод-вывод консоли/терминала? Интересный факт: в интерпретаторе bash если нажать [Ctrl]+[C], он перехватывает сигнал и на терминал выводится символ новой строки вместо ^C. Вот код из исходников bash - файл sig.c:
Вот еще интересный кусочек из исходников bash - файл jobs.c, правда относящийся к job control(в комментарии ясно написано что выводом ^C занимается обработчик ядра):
|
| Автор: MAKCim 27.3.2009, 15:47 |
bash лишний в цепочке и bash, и программа используют один и тот же /dev/pts/X а вообще меня самого заинтересовало как-нибудь на досуге разрулю этот вопрос |
| Автор: savigm 28.3.2009, 01:31 |
| stty -echoctl - действительно помогает, но я решил проблему иным путем: т.к. моя программа не использует ввод, то я просто отрубил ECHO в начале программы и включил в конце, но это все work around, суть вопроса по прежнему не ясна. Насколько я понимаю все дело в настройках терминала, т.е. по идее на терминале должно отобразится что-то типа ^[[ и т.п. а терминал преобразует это в ^C ^Q и т.п. |