Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lections_v2.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
10.99 Mб
Скачать

Принятые соглашения и стандарты.

Открытие псевдотерминала.

openpty()

login_tty()

forkpty()

Специально оговаривается, что существует большое количество способов открытия псевдотерминалов. В Линукс открытие псевдотерминала осуществляется в соответствии со стандартами, подобными стандартам SystemV. Открытие псевдотерминалов в соответствии с практикой BSD считается устаревшим способом. Существуют методы, реализованные как часть glibc, которые являются расширениями BSD. Также существует метод, документированный как стандарт Unix 98. Исторически существует два различных метода открытия псевдотерминала в Юникс. Линукс сначала придерживалась модели BSD и из-за сложности этой модели Линукс от нее отказался, перейдя на модель SysV, хотя в SysV реализован STREAMS. В Линукс STREAMS не реализован. Поскольку в результате исторического развития Линукс пришел к модели SysV, казалось бы, должна быть в Линукс реализована подсистема streams, но интерфейс Unix 98 не определяет функции, присущие streams. В результате в Линукс добавлена поддержка псевдотерминалов по стандарту Unix 98. При этом ядро линукс может быть скомпилировано без поддержки интерфейса Юникс 98, встречаются также старые версии без псевдотерминалов стиля Юникс 98.

Простые способы открытия псевдотерминалов.

int openpty(int *masterfd, int *slavefd, char *name, struct termios *term, struct winsize *winp);

int forkpty(int *masterfd, char *name, struct termios *term, struct winsize *winp);

Функция openpty() открывает ведущие и подчиненные псевдотерминалы не обязательно используя структуры termios и winsize, которые передаются как опции настройки псевдотерминала. В случае неудачи возвращается единица. Файловые дескрипторы ведущего и подчиненного устройств (masterfd, slavefd) возвращаются как аргументы. Последними параметрами являются term и winp, могут быть переданы как null и будут игнорироваться – соответствующие настройки выполняться не будут.

В отличие от openpty(), forkpty() вместо возврата slavefd разветвляет псевдотерминал как управляющий терминал для дочернего процесса. (Управляющий терминал – терминал, с которого подаются команды. С ним связаны три стандартных потока – stdin, stdout, stderr.) Родительскому процессу будет возвращен ID дочернего процесса, самому дочернему процессу будет возвращен 0 и -1 в случае неудачи. То есть, разветвляется не процесс, а терминал.

Для того, чтобы избежать различных проблем с использованием openpty и forkpty (проблемы возникают из-за того, что неизвестен размер буфера) рекомендуется в поле name передавать null и использовать функцию ttyname(), чтобы получить полное имя псевдотерминала.

tcgetattr(STDIN_FILENO, &term);

ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);

pid = forkpty(&masterfd, NULL, &term, &ws);

Сложные способы открытия псевдотерминала. (Относятся к интерфейсу Юникс 98.)

// сложные способы открытия псевдотерминала

#define _XOPEN_SOURCE 600

#include <stdlib.h>

#include <fcntl.h>

------------

int posix_openpt(int oflag);

int grantpt(int fildes);

int unlockpt(int fildes);

char *ptsname(int fildes);

Пример forkpty

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <pty.h>

#include <termios.h>

#include <fcntl.h>

#include <sys/select.h>

#include <sys/wait.h>

int main()

{

int master;

pid_t pid;

pid = forkpty(&master, NULL, NULL, NULL);

if (pid < 0)

return 1;

else if(pid == 0)

{

char *args[] = NULL;

execvp("user/bin/bc", args);

}

//parent

// remove the echo

struct termios tios;

tcgetattr(master, &tios); // получение параметров работы теримнала

tioc.c_lflagf = ~(ECHO|ECHONL);

tcsetattr(master, TCSAFLUSH, &tios);

for (;;)

{

fd_set read_fd;

fd_set write_fd;

fd_set except_fd;

FD_ZERO(&read_fd);

FD_ZERO(&write_fd);

FD_ZERO(&except_fd);

FD_SET(master &read_fd);

FD_SET(STDIN_FILENO, &read_fd);

select(master+1, &read_fd, &write_fd, &except_fd, NULL);

char input;

char output;

if (FD_ISSET(master, &read_fd))

{

if (read(master, &output, 1) != -1)

write(STDOUT_FILENO, &output);

else ; // тут был break

}

if (FD_ISSET(STDIN_FILENO, &read_fd))

{

read(STDIN_FILENO, &input, 1);

write(master, &input, 1);

}

}

return 0;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]