Предпочтительный способ работы с struct termios
заключается в использовании цикла чтение-модификация-запись, но данному случаю это не соответствует по двум причинам. Можно передать NULL
и принять значения по умолчанию, что достаточно в большинстве случаев; а когда вы хотите предоставить настройки termios
, вы часто заимствуете настройки у другого tty, или знаете точно, какими они должны быть (например, в случае концентратора последовательного порта SCSI, описанного ранее в этой главе).
tcgetattr(STDIN_FILENO, &term);
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
pid = forkpty(&masterfd, NULL, &term, &ws);
16.6.3. Сложные способы открытия псевдотерминалов
Интерфейс Unix98 для распределения пары псевдотерминала представляет собой следующий набор функций.
#define _XOPEN_SOURCE 600
#include
#include
int posix_openpt(int oflag);
int grantpt(int fildes);
int unlockpt(int fildes);
char * ptsname(int fildes);
Функция posix_openpt()
— это то же, что и открытие устройства /dev/ptmx
, но теоретически она более переносима (поскольку везде принимается). Рекомендуется в этот раз использовать open("/dev/ptmx", oflag)
для максимальной практической переносимости. Если вы хотите установить один или два флага open()
или posix_openpt()
, используйте O_RDWR
, как обычно; если вы вместо этого не открываете управляющий tty для процесса, используйте O_RDWR | O_NOCTTY
. open()
или posix_openpt()
вернет открытый файловый дескриптор управляющему устройству псевдотерминала. Затем вызовите grantpt()
с файловым дескриптором управляющего устройства псевдотерминала, возвращенным из posix_openpt()
, для изменения режима и владельца подчиненного компонента псевдотерминала, а потом — unlockpt()
, чтобы сделать подчиненный компонент псевдотерминала доступным для открытия. Интерфейс Unix98 для открытия подчиненного устройства псевдотерминала должен просто открыть имя, возвращенное ptsname()
. Все эти функции возвращают -1
в случае ошибки, кроме ptsname()
, возвращающей в такой ситуации NULL
.
Функции в ptypair.c
распределяют согласованную пару устройств pty. Пример функции get_master_pty()
в строке 22 ptypair.с
открывает управляющее устройство pty и возвращает файловый дескриптор родительскому процессу, а также предоставляет имя соответствующему подчиненному компоненту pty. Он сначала испытывает интерфейс Unix98 на распределение управляющего устройства pty, а если это не работает (например, если ядро скомпилировано без поддержки pty Unix98, возможно, для встроенных систем), возвращается к старому интерфейсу стиля BSD. Соответствующая функция get_slave_pty()
в строке 87 может быть использована после fork()
для открытия соответствующего подчиненного компонента pty.
1: /* ptypair.c */
2:
3: #define _XOPEN_SOURCE 600
4: #include
5: #include
6: #include
7: #include
8: #include
9: #include
10: #include
11: #include
12:
13:
14: /* get_master_pty() принимает дважды косвенный символьный указатель на
15: * место помещения имени подчиненного компонента pty и возвращает целочисленный
16: * файловый дескриптор. Если возвращается значение < 0, значит, возникла ошибка.
17: * В противном случае возвращается файловый дескриптор ведущего устройства pty
18: * и заполняет *name именем соответствующего подчиненного компонента pty. После
19: * открытия подчиненного компонента pty, вы отвечаете за освобождение *name.
20: */
21:
22: int get_master_pty(char **name) {
23: int i, j;
24: /* значение по умолчанию, соответствующее ошибке */
25: int master = -1;
26: char *slavename;
27:
28: master = open("/dev/ptmx", O_RDWR);
29: /* Это эквивалентно, хотя и более широко реализовано,