TTY Subsystem
Maxm Sokhatsky (maxim@sokhatsky.com)
Termios
According to Single UNIX Specification Version 2 Ц General Terminal Interface (termios.h their structures, functions and constants) defines the way to deal with termios Terminal Structure. The main purpose of public part of specification is to provide set of constants to manage the terminal, i.e. on which codes and how terminal must answers. The private part (how driver must collect data, input and output queues, synchronization) is free to interpretation. Most common set of flags constants covers POSIX, BSD and XOPEN vision of the matter.
In other words the main purpose of Terminal Interface is to convert characters on input and output streams from symbols to device interpretable commands. The main conversion logic is concentrated in *read* and *write* subroutines of terminal driver.
The termios service (I mean *ioctl*) handler codes are also free to implementation but in general there are some *standard* codes used in BSD and System V like systems, and thereby software relays on that implementations.
Line disciplines
As was mentioned above - one of the main purpose (besides unification of dealing with character input/output human devices) of terminal interface is to convert data streams (e.g. when we recognize " " in *write* stream we must send to message to display part of terminal "carriage return" and "new line" commands. Besides *read* and *write* routines alongside of them are *open*, *close* and *ioctl* operation that also may have some not-traditional logic for certain conversion mode. That conversion layers calls Line Disciplines. Thus line discipline is a set of terminal driver handler on of them can be chosen for fixed termios instance.
Custom Line discipline (besides) is used to handle conversion modes e.g. for standard TTY, MOUSE, PPP, SLIP protocols. Many variants of those protocols can be obtained and used in one application. On most Unix-like OS Termios structure has c_line field used to select line discipline.
Teletype Discipline
Teletype driver consists of standard conversion logic (*read* and *write* subroutines) the service logic (*ioct*, handler codes). This means exact the discipline - standard tty discipline used in most cased when used terminal subsystem. E.g. it is used in conjunction with device drivers, like pty, com, ppp, slip, and may others. Teletype driver is not working with devices directly it just converts char from raw to canonical form.
Terminal Drivers
The most wide known variants of tty drivers are pty master/slave drivers and serial line drivers. Other using of tty is covering by ppp, slip and others communication stacks. The terminal driver is responsible to handle the control characters in stream and convert it to device commands, control of it sending to device along with input/output character stream to device.
In theory each terminal driver can use their own discipline or set of disciplines along with providing no discipline. If the terminal driver provides no discipline - the common Teletype Discipline is using. From other side one discipline can be used with two or more teletype driver. I.e. discipline is not connected directly "one to one" with device type. Also terminal can always use teletype discipline as wide known discipline.
Line disciplines are distensible
I.e. you could implement your own line discipline and use it in you application or terminal drivers. For example there is no need to implement all possible and used in industry line disciplines - but must be an elegant way to extend them. Thus discipline is loadable module that can be obtained by its name.
The main teletype discipline is one of the always known disciplines when working with terminal is needed and is responsible for storing information about other disciplines and their using.
Module 1 +----------------------+
Module 2 Module 3
+---------+ +------+ +------+ +------+
DISCIPL TTY PPP SLIP
MANAGER DISC DISC DISC
+---------+ +------+ +------+ +------+
+----------------------+
That means that TTY discipline module is not like other discipline module - it is main - and hosts discipline array structure. TTY discipline is some kind of master discipline. Let us see examples on how disciplines are used in TTY stack.
Example 1. RS232 Driver - the same is PTY driver
+---------------+
| USER APP |
+---------------+
V
+-----------+ +-----------------+
| COM |->| TTY |
| DRIVER |<-| DISCIPLINE |
+-----------+ +-----------------+
V
+----------------+
| HARDWARE |
+----------------+
Example 2. PPP Driver
+------------+
PPP client User App
+------------+
V
+----------------+ +--------+ ->
PPP DISCIPLINE PPP <-+----------------+ DRIVER ->+----------------+
+--------+<- TTY DISCIPLINE +----------------+ +--+-------+------------+ V V V +--------+ +--------+ +--------+ COM USB NET DRIVER DRIVER DRIVER +--------+ +--------+ +--------+
For example I can (from user app) say to PPP driver not to use PPP discipline but instead your own implemented TEST Discipline. The mechanism of selection underlying hardware is of scope of work of Network Team. TTY subsystem just must provide proper mechanism to using with tty disciplines for authors of PPP driver.
+-----------------+
+--------+-> TEST DISCIPLINE
PPP <-+-----------------+ DRIVER ->+----------------+
+--------+<- TTY DISCIPLINE +----------------+
This can be done by changing c_line flag in termios structure associated with opened file device.
But that can't guaranteed that all drivers must handle that. E.g. in PPP driver is used two disciplines one can be substained but second is always tty. You could change just one discipline by the termios interface. But driver can use more than one discipline in its conversion logic.
Я себе купил PowerMac 9600. Две сетевые карты 10 и 100 МБит, USB, карта переходник с процессором G3 750 400Mhz, внешний CDRW, два винчестера по 4 ГГб с установленными Mac OS 9.2.2, Mac OS 8.5, BeOS 5 Pro и BeOS Dano. Layout такой: четыре раздела по 2 ГГб на двух 4 гигабайтовых винчестерах. На первом винчестере только Мак, на втором только БеОС. Надо снесни минимум один раздел. Думаю какой. Хочу поставить туда Debian.
После того как я давно не появлялся в сети с сообщениями по поводу статуса Haiku. Хочу сообщить что в украинском сообществе дела обстоят гораздо лучше чем планировалосю. Есть уже 3 человека (включая меня) которые хотят выделять время на хакинг Хайку. Но обо всем по порядку.
Пауза была вызвана тем что Хайку переезжали на новый SVN репозиторий. По ходу за это время было много сделано: самые главные достижения PCI IDE, новый мехенизм загрузки драйверов (посмотрения дерева драйверов), работающий AppServer и запуск MiniTerminal в AppServer. Кроме того дерево исходников выросло в 5 раз (из-за того, что SVM хранит историю изменений локально, что бы не бегать в сеть, а также из-за большого количества нового: включен gdb который портирован под хайку и работает :) (Следующим я так понимаю будет включение gcc). Хочу отметить что gcc впринципе в кору не падает когда пускаешь, но собирать пока не пробовали.
В данный момент Мастер (oleg.smirnov@gmail.com) берет на себя все вопросы по TCP/IP стеку который можно смело называть пока BSD стеком, так как только эти исходники в основном там есть ну и роадмап что как хотелось бы видеть. Включили в дерево Хайку также Bind 9.2.3 :).
IDKFA (Andriy Skulysh) наверно будет заниматься PCMCIA стеком, что того чтобы получить WiFi. Также степень интересов его гораздо больше, но в основном - это конечно тоже ядро newos.
Итак необходимо было выкачать последний снепшот и собрать Хайку. В прошлый раз (CVS) я остановился на том что не мог попасть в шелл. Система висла после инициализации фреймбуфера на этапе загрузки драйверов. Так как эта часть была полностью переписана, ожидания были самыми оптимистичными.
Итак система собралась (не с первого раза). Надо не забывать о переменной TARGET_PLATFORM=haiku которая выставляется в makehdimage и нужна нескольким модулям для корректной линковки. Когда же билдить просто jam как раньше, то эта перменная не соотв. не установлена, файлы не линковались, и в результате билд файлится. Теперь всегда надо билдить с помощью скрипта makehdimage.
Загрузилась удачно в шелл. Это достижение. Читайте следующее сообщение про запуск app_server и MiniTerminal.
После приобретения SMP материнской платы с процессора я решил провести испытания SiSoft Sandra 2005 Lite. Она показала такие результаты моей машины:
Motherboard: i815 (Solano)
Momery: PC133
CPU: 2x Pentium III 933MHz
CPU: Dhrystone 6718, Whetstone 2607;
Multimedia: Integer x4 iSSE 16113, Floating-Point x4 iSSE 20253;
Мemory Bandwidth: RAM Bandwith Int Buffered iSSE 689, RAM Bandwith Floating-Point Buffered iSSE 673;
Показатели памяти такие плохии потому, что это PC133. RAMBUS, например, в 4 раза быстрее. К примеру, по словам сандры, моя машина точно такая по скорости как Pentium 2.4 ГГц. Возникает вопрос: зачем платить больше? Отсюда вывод - SMP - это хорошо.
Я думаю все сталкивались с проблемой в виндовсе когда на форме куча белых квадратов, мыша не двигается, а в это время на винчестере происходят разные вещи. Это от того что у людей которые пишут программы нету многопоточной культуры.
Представим себе ГиперМега полезную программу, которая, например, читает\пишет какие-то файлы. Играясь, по ходу написания программы, в основном сосредоточившись на алгортме обработки, был написан для него ГУИ интерфейс. Как запустить алгоритм ?, - допустим кнопкой. Например алгоритм - СделатьПолезное. Хорошо если данные маленькие, а если большие ? Тут вы скажете, что это всего-лишь 2% случаев, и доводку можно списать на суппорт или как исправление багов. Но именно это всегда причина того что как говорят неискушенные "виндовс залипает". Все потому, что люди не понимают что такое потоки и их важность. Или увидели в книге "используйте потоки осторожно" и боятся их юзать. Чужь. Юзать нужно почти всегда и везде.
Допустим у нас жесткие условия, чем сложнее алгоритм - тем он проще. Как заставить писать в потоковом режиме используя буферизацию писать в разные места на диске большие объемы данных ? Очень просто - while (true) printf("xxxxxxxxxxxxx"); Вы себе не представляете какая махина за этим стоит - очереди, Interrupt Request Packets, семиуровневая подель шины драйверов, многопоточные драйвера файловой системы, буферизация. Вообщем не будем изобретать велосипед, а заюзаем эту махину, все равно ничего круче чем в NT не видел. Это и будет наш алгоритм - СделатьПолезное. В первом приближении, представьте себе, что это конвертор AVI.
using System;
using System.IO;
using System.Windows.Forms;
using System.Threading;
public class ГиперМега : Form {
public void УбийцаВремени() {
StreamWriter Полезное = new StreamWriter("ТутЛежитПолезное");
while (true) Полезное.Write("Буратина был тупой ");
}
public void ПередайДальше(object sender, EventArgs e) {
Controls[0].Enabled = false;
УбийцаВремени();
}
public ГиперМега() {
Text = "УльтраСупер";
Button батон = new Button();
батон.Text = "Поджигай";
батон.Click += new EventHandler(ПередайДальше);
Controls.Add(батон);
}
public static void Main() {
ГиперМега СуперУльтра = new ГиперМега();
Application.Run(СуперУльтра);
}
}
Ну вот и написали нашу чудную программу. Хочу вас попросить что бы вы компилировали ее как консольную, почему увидите позже. Поджигаем. И сразу пробуем переместить окошко. Получилось ? Хрен. Почему ? Потому что наш алгоритм СделатьПолезное превратился в УбийцуВремени. Заблокировал поток в котом рисуется ON_PAINT а также где обрабатываются все другие сообщения. Нажмите ^C в консоли. На крест не поможет. За 10 секунд эта прога создст у вас около 50 МБ. Вообщем .NET в этом плане молодец.
А представите теперь что это обычный обработчик кнопки на который вы используете какое-то чужое АПИ, например ходите в базу, или еще какой-то. Вы уверены, что "там" не дойдет до while (true) ? В большенстве случаев как раз именно и на этом "залипают" все проги.
"I шо його робити дорога редакція?". Да всего лишь вынести в поток обработчик.
using System;
using System.IO;
using System.Windows.Forms;
using System.Threading;
public class ГиперМега : Form {
Thread Worker;
public void СделатьПолезное() {
StreamWriter Полезное = new StreamWriter("ТутЛежитПолезное");
while (true) { Полезное.Write("Буратина был тупой "); }
}
public void ПередайДальше(object sender, EventArgs e) {
Controls[0].Enabled = false;
Worker = new Thread(new ThreadStart(СделатьПолезное));
Worker.Start();
}
public ГиперМега() {
Text = "УльтраСупер";
Button батон = new Button();
батон.Text = "Поджигай";
батон.Click += new EventHandler(ПередайДальше);
Controls.Add(батон);
}
protected override void OnClosed(EventArgs e) {
Worker.Abort(); // освободите ресурс
}
public static void Main() {
Application.Run(new ГиперМега());
}
}
И делайте это как можно чаще. И что все обработчики кнопок выносить в отдельные потоки? Я отвечу. Дело в том что архитектура винды не разделяет окно на два потока, один который реагирует на внутренние сообщения, а другой на сообщения пользователя. От этого вся ерунда. Поэтому каждому програмимсту надо изобретать велосипед от "залипания". Можете например в гугле поискать "Worker Controller UI Thread" там написано как нужно разделять оконные и пользовательские потоки в .NET.
Кстати замечу, что в этом примере, надо освобождаться от ресурсов. Потому что поток это такой хитрый ресурс который если не остановить прямо, навсегда потеряется в недрях CLR до Collect и долго еще вам будет писать на винчестер пока диск не кончиться =)
Добавлю, что во-первых, из-за того, что в BeOS для каждой формы отдельный ГИУ поток (он называется picasso), она ведетсебя так мягко. И инвалидных регионов закрашеных белым вы там никогда не увидите. Даже если запустить 1000 программ, все равно все будем мягко, с каждым разом все медленне и медленне но все будет плавно. А описаных выше проблем там нет. Во вторых люди которые писали приложения для BeOS не ленились нигде проверять количество процессоров в системе и исходя из этого создавать количество потоков. Согласитесь, для большинства, кто пишет под виндовс и в голову такое не придет. Вообщем, тема - многопоточная культура =)