
- •Лекция 1. 7.02.2014
- •Монтирование файловой системы.
- •Лекция 2. 10.02.2014
- •Лекция 3. 17.02.2014
- •Открытые файлы.
- •Лекция 4. 24.02.2014
- •Лекция 5. 3.03.2014 Файлы.
- •Лекция 6. 17.03.2014
- •Организация виртуальной файловой системы (vfs)
- •Регистрация и дерегистрация фс
- •Функции для работы с элементами фс proc.
- •Лекция 7. 24.03.2014
- •Файловая система specfs.
- •Терминалы.
- •Терминальный ввод-вывод.
- •Лекция 8. 31.03.2014
- •Типы флагов структуры termios.
- •Принятые соглашения и стандарты.
- •Простые способы открытия псевдотерминалов.
- •Лекция 9. 7.04.2014
- •Лекция 10. 14.04.2014
- •Реализация доступа к устройствам.
- •Структура контроллера внешнего устройства.
- •Южный и северный мосты.
- •Последовательные и параллельные интерфейсы.
- •Лекция 11. 21.04.2014
- •Управление вводом-выводом.
- •Прерывания.
- •Лекция 12. 28.04.2014 Контроллер прерывания.
- •Лекции 13-14. 5.05.2014, 12.05.2014
- •Проблемы прямого доступа к памяти.
- •Управление устройствами.
- •Многослойная модель системы ввода-вывода.
- •Пространство имен устройств.
- •Доступ к драйверу символьного устройства.
- •Доступ к драйверу блочного устройства.
- •Дополнительная информация о драйверах.
- •Лекция 15. 19.05.2014
- •Типичные точки входа в драйвер устройства.
- •Файлы устройств.
- •Буферизация ввода-вывода.
- •Схемы обменной буферизации
- •Обслуживание прерываний.
- •Лекция 16. 26.05.14
- •Лекция 17. 02.06.14
Принятые соглашения и стандарты.
Открытие псевдотерминала.
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;
}