Multi-Head
Introdução
MultiHead vêm do inglês "cabeças
múltiplas". Na prática é como colocar
várias pessoas usando a mesma máquina sem uma atrapalhar
a outra.
Muitos dos usuários de computadores não imaginam o que os
computadores
ainda podem fazer. Vemos nos filmes de ficção coisas
engenhosas que
controlam e facilitam a vida das pessoas. O que geralmente é um
erro de
se pensar é que muitas das inovações só
virão com a evolução técnica da
engenharia e arquitetura. Na prática basta uma idéia
simples para que
tudo que se evoluiu até o presente momento possa ser abandonado
ou
potencializado. Então, além de aumentar a
capacidade dos recursos é
importante usá-los de forma plena.
A idéia do multi-head é baseado nesta
otimização e melhor
aproveitamento dos recursos que temos. Essa é uma idéia
que surgiu
basicamente da comunidade de software livre. Acho que a maior e
primeira referência no assunto foi Alvils Stoss um
letão (nascido na
Letônia) que escreveu um patch para o kernel chamado Backstreet
Ruby.
Esse patch foi bem assimilado pela comunidade e mais tarde possibilitou
o servidor X a suportar nativamente o conceito sem
adaptações. O
servidor X é "um capítulo a parte". Na verdade a
concepção dos sistemas
Unix definem os recursos de vídeo através de uma
aplicação remota
cliente-servidor (X). E pelo X já ter esta natureza possibilitou
configurações diversas de computadores e terminais. Na
prática pode até
ser que isso traga um desempenho um pouco menor mas traz um recurso
poderoso.
Os requesitos não são muitos. Os
recursos que você precisa para
rodar pelo menos 2 terminais são muito baixos. Se você
tiver 1 teclado
usb, 1 mouse usb, e uma placa com duas saídas de vídeo
(até mesmo 1
saída de TV) já existe a possibilidade de configurar o
seu multihead.
Na teoria o número de usuários podem usar simultaneamente
apenas uma
CPU é bem grande. Existem placas Desktop com até 6 slots
PCI mais 1 AGP
ou video onBoard. Todos os slots podem ser usados, e se considerarmos
cada slot com uma placa de duas saídas conseguiríamos
rodar
praticamente um laboratório inteiro!
Não tem quem veja uma solução
pronta rodando e não fique igual criança
com brinquedo novo. . . Essa solução deu novas
perspectivas a montagem
de um laboratório e pode reduzir e muito os custos dos mesmos.
Os micro-processadores evoluíram muito ao
longo da sua história. Os
computadores que temos hoje são computadores de grande
capacidade de
processamento. Enquanto as tarefas básicas, mesmo com todos os
recursos
gráficos, não são um verdadeiro desafio para o
processamento em geral.
Os usuários que gostam de ter gráficos com
histórico do uso da CPU
podem constatar que, há um grande período que a CPU fica
ociosa. Você
pode fazer um teste habilitando o monitor do sistema na barra do Gnome
ou usando o Superkaramba. No uso geral o gráfico se mostra mais
ou
menos com picos:
Exemplo:
Supondo que este é um histórico de uso
esperado dos usuários, se os
picos não coincidirem entre eles o
resultado(sensação do usuário) vai
ser igual a de um computador dedicado. Por outro lado se os picos
coincidirem você terá divisão do desempenho pela
quantidade de
coincidências que ocorrerão. Para teorizar estas
informações podemos
usar um exemplo. Consideremos "picos" os momentos que a CPU passou de
50% de uso e se manteve por pelo menos 1 segundo e no máximo 2
segundos. Durante o meu teste de uso que abri alguns emails e editei
este texto tive 2 picos em 2 minutos. Se tivéssemos 2
usuários, com o
mesmo tipo de uso, a probabilidade de haver um momento de
colisão dos
picos é muito baixa (perto de 5%,
dúvidas?).
Porém quanto mais usuários, mais alta essa probabilidade
vai ser e mais rápido ela cresce (
visto
que ela não é uma função linear).
É possível fazer mais estudos dessa forma, mas isto pode
não ser
adequado pois não podemos prever o que cada usuário vai
fazer. Então a
única ferramenta adequada pode ser uma pesquisa com os
usuários
perguntando a sensação que cada um teve ao usar o
computador.
É claro que algumas aplicações
como jogos por exemplo exigem um
processamento grande e contínuo. Mas tarefas como tarefas de
escritório
este gráfico é bem exemplificado. Então podemos
partir do princípio que
seus usuários não vão jogar pesados jogos 3D (no
máximo jogos em flash
da internet). Porém nem tudo num computador é CPU. Esse
tipo de
ambiente traz outros tipos de desafios. Por exemplo: o acesso a disco!
Os discos rígidos são dispositivos que eu,
particularmente, considero
verdadeiros dinossauros da informática. Eles são lentos e
tem uma
latência muito grande. Pior que isso, tendem a ficar mais lentos
quando
os acessos são não seqüenciais ou seja em setores
distantes. O que nos
leva a concluir que um ambiente de multiterminais é o pior
ambiente
possível para acesso a discos (visto que os usuários
são independentes).
Mesmo tendo estes desafios o Linux nativamente
já usa as melhores alternativas de amenização dos
problemas. Como por exemplo:
- Cache de disco em memória.
- Bibliotecas compartilhadas.
- Filosofia Unix de multi-usuário.
- Além da atribuição do Linux como sistema
para servidores.
O cache de disco em memória possibilita que
pequenos acessos sejam
imperceptíveis. Por outro lado o uso de bibliotecas
compartilhadas faz
com que programas já abertos sejam aproveitados entre
vários usuários
de forma transparente. O administrador da máquina pode (e
é desejável)
configurar o sistema de forma a não possibilitar diversas
implementações que não são compartilhadas.
Por exemplo, numa mesma
máquina instalado KDE e GNOME. Visto que um usa QT e o outro GTK
e não
compartilham nada entre eles. Essas facilidade que o linux apresenta
faz com que o multiterminal funcione bem até em um Celeron
1.6 Ghz com
128 mb de RAM. Pelo menos 512MB de RAM e HD Sata é recomendado.
Outra coisa que vale a pena ressaltar: Para
configurar seu ambiente
multiterminal é necessário ter uma certa
experiência com Linux.
Colocando as placas e achando elas no sistema
Bom, tanto faz a ordem dos dispositivos USB ou
então das placas, só
coloque-as em qualquer ordem. Procure não fazer a
instalação do
Linux com elas plugadas. Em distros
como o
Mandriva,
alguns programas de detecção automática travam ou
então tentam configurar
automaticamente todas elas e ocorrem problemas.
Agora verifique se está instalado o Xorg,
hotplug, udev e tudo
configurado no boot. Dentre as formas de fazer escolherei a mais
simples.
Mais pra frente passarei rapidamente sobre as outras.
Tendo tudo funcionando, entre no shell e dê um
lspci:
$ lspci
....
0000:00:09.0 VGA compatible controller: ATI Technologies Inc Rage 128
RK/VR
0000:00:0a.0 VGA compatible controller: ATI Technologies Inc Rage 128
RK/VR
0000:00:0b.0 VGA compatible controller: ATI Technologies Inc Rage 128
RK/VR
0000:01:00.0 VGA compatible controller: Silicon Integrated Systems
[SiS] 661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP
Anote os endereços que estão ali no
primeiro campo, caso saiam muitos
dispositivos, um "grep VGA" ajuda. Descubra também quais
módulos são
carregados pra cada dispositivo.
Agora está na hora de verificar os
dispositivos USB. Pode parecer bobagem
eu falar isso, mas verifique mesmo se estão plugados um
número muito grande
assim de dispositivos sempre tem um mal encaixado e você perde um
dia
inteiro à toa. No shell mesmo dê um cat no /proc:
$ cat /proc/bus/input/devices
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
H: Handlers=kbd event0
B: EV=120013
B: KEY=4 2000000 3802078 f840d001 f2ffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7
I: Bus=0011 Vendor=0002 Product=0005 Version=0000
N: Name="ImPS/2 Generic Wheel Mouse"
P: Phys=isa0060/serio1/input0
H: Handlers=event1 mouse0 ts0
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=103
I: Bus=0003 Vendor=0a81 Product=0101 Version=0110
N: Name="CHESEN USB Keyboard"
P: Phys=usb-0000:00:03.0-1/input0
H: Handlers=kbd event2
I: Bus=0003 Vendor=0a81 Product=0101 Version=0110
N: Name="CHESEN USB Keyboard"
P: Phys=usb-0000:00:03.0-1/input1
H: Handlers=kbd event3
I: Bus=0003 Vendor=0566 Product=3002 Version=0100
N: Name="0566:3002"
P: Phys=usb-0000:00:03.0-2/input0
H: Handlers=kbd event4
I: Bus=0003 Vendor=1267 Product=0210 Version=0001
N: Name="PS/2+USB Mouse"
P: Phys=usb-0000:00:03.0-3/input1
.... (e tudo mais lá pra baixo)
Veja que o mesmo teclado "CHESEN USB Keyboard" tem o
mesmo endereço
físico, mas tem duas entradas. Isso se deve as teclas especiais
como
desligar, suspender, navegação na internet e "Windows"
que o kernel
trata como um teclado separado. Aqui iremos só usar o primeiro
input.
Anote o endereço físico (PHYS) de cada um.
Tendo isso agora vamos para o próximo passo.
Começando a por a mão na massa
Dentre os problemas que envolvem os
multiheads,
existem
alguns realmente chatos. As placas não são projetadas pra
funcionar
de forma independente. Uma placa sempre derruba a outra, às
vezes
aparecem caracteres estranhos em uma delas e a tela misteriosamente
começa a rodar com um simples mount ou swapon.
Por exemplo, uma interrupção pode ser "entendida" por
todas elas. Isto
acontece com a int 10. Quando a placa é inicializada.
Porém simplesmente
tirando a interrupção 10 faz com que as placas
secundárias não tenham
memória suficiente para inicializar (sem modos de tela
válidos).
Mas calma, não é o fim do mundo. Para isso dá-se
um jeito, colocando um
script simples no boot que chamaremos de "Xorg-multiterminal". Ele
só
inicializará as placas sem a interrupção 10 pra
que depois elas sejam usadas.
Mas primeiro vamos configurar o xorg.conf, edite o
/etc/X11/xorg.conf
mais ou menos com a seguinte configuração, mudando os
endereços pelo qual
você anotou:
....
Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "Protocol" "evdev"
Option "Dev
Phys" "isa0060/serio0/input0"
Option "XkbRules" "xorg"
Option "XkbModel" "pc104"
Option "XkbLayout"
"us"
Option "CoreKeyboard"
EndSection
Section "InputDevice"
Identifier "Keyboard1"
Driver "kbd"
Option "Protocol" "evdev"
Option "Dev
Phys" "usb-0000:00:03.0-1/input0"
Option "XkbRules" "xorg"
Option "XkbModel" "pc104"
Option "XkbLayout"
"us"
Option "CoreKeyboard"
EndSection
Section "InputDevice"
Identifier "Keyboard2"
Driver "kbd"
Option "Protocol" "evdev"
Option "Dev
Phys" "usb-0000:00:03.0-2/input0"
Option "XkbRules" "xorg"
Option "XkbModel" "pc104"
Option "XkbLayout"
"us"
Option "CoreKeyboard"
EndSection
Section "InputDevice"
Identifier "Mouse1"
Driver "mouse"
Option "Protocol" "evdev"
Option "Dev
Phys" "usb-0000:00:03.2-1/input1"
Option "CorePointer"
Option "ZAxisMapping" "4
5"
EndSection
Section "Device"
Identifier "Device0"
Driver "sis"
BusID
"PCI:1:0:0"
Option "NoInt10"
"Yes"
Option "RestoreBySetMode" "no"
EndSection
Section "Device"
Identifier "Device1"
Driver "ati"
BusID
"PCI:0:9:0"
Option "NoInt10"
"Yes"
Option "RestoreBySetMode" "no"
EndSection
Section "ServerLayout"
Identifier "Layout0"
Screen "Screen0"
InputDevice
"Keyboard0"
InputDevice
"Mouse0"
Option "SingleCard"
EndSection
Section "ServerLayout"
Identifier "Layout1"
Screen "Screen1"
InputDevice
"Keyboard1"
InputDevice
"Mouse1"
Option "SingleCard"
Option
"DontZap" "on"
EndSection
Aqui omiti várias informações, porém o
principal ainda se encontra
aí. Interessante também é desabilitar a
aceleração 3D, já que não vai
ser necessário mesmo, coloque Option "NoAccel" em cada device. A
opção Dontzap no layout impede que o usuário feche
o X com
Ctrl+Alt+Backspace. Isso faz com que todos os usuários caiam.
Atenção!
o BusID usa endereços em decimal.. então converta a =10,
b=11, c=12...
Outra coisa muito importante é o driver
evdev (event
devices),
ele é o responsável pela separação dos
dispositivos em distros como
Mandriva e evdev não vem
compilado no Xorg.
Infelizmente
você
vai ter que compilar e o trabalho vai durar semanas. Outra
solução é
usar o /dev/input ao invés do endereço físico, mas
sua distro deve suportar os protocolos.
Agora precisamos configurar o "Xorgmultiterminal" no boot. Pra isso
crie
um arquivo "xorg.conf.probe", que será baseado no xorg.conf. Ele
habilita
as placas no boot. Então crie o /etc/X11/xorg.conf.probe
começando já
da placa secundária:
Section "Device"
Identifier "Device1"
Driver "ati"
Screen 0
BusID
"PCI:0:9:0"
Option "NoInt10"
"no"
Option "NoAccel"
Option "RestoreBySetMode" "no"
EndSection
.....
Section "ServerLayout"
Identifier "probe"
Screen "Screen1"
Screen "Screen2"
LeftOf "Screen1"
Screen "Screen3"
LeftOf "Screen2"
InputDevice
"Keyboard1"
InputDevice
"Mouse1"
EndSection
A ordem das telas não importa. Note que só são
inicializadas as placas secundárias. E a
interrupção 10 está como "NO".
Agora precisamos colocar na inicialização. Crie um script
/etc/init.d/xorgmultiterminal com a seguinte linha de
comando:
[[ -f "/etc/X11/xorg.conf.probe" ]] && /usr/X11R6/bin/X -config
/etc/X11/xorg.conf.probe -probeonly
Agora descubra qual runlevel corresponde ao modo multi-usuário
com X11 na sua distro dando um cat no /etc/inittab.
Vamos supor que seja o
Debian, que é 3. Então
entre em
/etc/rc3.d e crie um link simbólico com:
$ ln -s /etc/init.d/xorgmultiterminal S80xorgmultiterminal
O número 80 corresponde a prioridade que esse script tem no
boot.
Quando você parar o X, execute sempre ele novamente na mão
pra não
precisar reiniciar. Por exemplo:
$ /etc/init.d/gdm stop
$ /etc/init.d/xorgmultiterminal
.......
$ /etc/init.d/gdm start
Configurando o gerenciador de displays (gdm)
Acredito que o gerenciador mais modular de todos é o GDM,
justamente por isso que todos os lugares que descrevem conteúdo
sobre
multiheads explicam mais do GDM. Na verdade não
altera muito de um pra outro. Primeiro vamos testar o X. Abra no
terminal:
$ Xorg -layout Layout0
Depois feche o X e teste um por um dos layouts:
$ Xorg -layout Layout1
$ Xorg -layout Layout2
$ Xorg -layout Layout3
Tendo todos os layouts funcionando, teste o teclado com o numlock,
se todos os leds piscarem juntos, não está funcionando.
Tem que ser
independente. Configure o gdm em
/etc/gdm/gdm.conf da seguinte
maneira na seção servidores:
0=XServer0
1=XServer1
....
[server-XServer0]
name=Standard_server0
command=/usr/X11R6/bin/X -layout Layout0 :0 vt7 -sharevts
flexible=true
[server-XServer1]
name=Standard_server1
command=/usr/X11R6/bin/X -layout Layout1 :1 vt8 -sharevts
flexible=true
Em algumas distros como o
Mandrake, é necessário
um módulo do
kernel chamado Faketty, que cria terminais virtuais 50, 51, 52....
ao invés de 7, 8, 9. Estes vts "falsos" tem menos rigor no
controle
dos dispositivos. Mas isso é desnecessário pra distros
menos
userfriendlys, como Debian, Slackware, Gentoo e SuSE.
Para usar o XDM ou KDM é praticamente a mesma coisa, só
chame a mesma
linha de comando pra cada servidor. Em cada um deles você
provavelmente
tenha um resultado diferente. Mas o que eu tenho percebido é que
GDM
e XDM são os mais adequados.
Testando e usando
Agora é só usar. Procure não logar dois
usuários iguais. Eles costumam
interferir um no outro. Note também que com um "ps -aux"
dá pra ver
vários X sendo executados. Sempre procure logar 1 gerenciador de
janela
só, faça testes de desempenho e veja com é ruim
usar vários gerenciadores
grandes diferentes.
Essa configuração ainda tem problemas de estabilidade,
mas nada
preocupante. Você como administrador do sistema pode colocar
só uma
categoria de software e fazer com que os usuários usem da forma
que
você quiser.
Outro problema são as mensagens de erro. O
kernel
não se dá
conta do
multihead e sempre imprime na tela principal. Isso
causa
uma rotação da tela.
Pode-se ser resolvido com redirecionamento do erro 1> para /dev/null
ou recompilar o kernel sem suporte a console.
Um problema que tive e ainda não resolvi é o logout.
Todos os usuários
caem, mas isso não acontece em todas as placas. Isso depende
muito do driver da placa de vídeo.. alguns são mal
escritos.
Agradeço ao site
Que é de um carinha que desenvolveu um patch pro
kernel
pra fazer
multiheads. Ele explica MUITA coisa! A melhor fonte
da net
com
certeza.
Outro link interessante de onde tirei bastante
informação:
Multi-head usando udev e Xnest
Esta montagem contempla uma solução usada em algumas
ferramentas
proprietárias de multi terminais. Utiliza-se apenas um servidor
X
estendido (não xinerama) e coloca várias janelas do
tamanho da tela
para o uso do usuário. Cada janela é um processo que
recebe o event
fornecido pelo udev. A camada de baixo (X) o usuário não
pode ver, só o
Xnest que está na sua tela, que não pode ser
redimensionado. Para ter
acesso ao servidor X nest modificado pelo patch desenvolvido na UFPR
faça o download aqui:
Você precisará também do script feito por mim :)
Tendo todos estes arquivos vamos começar a por a mão na
massa.
Plugando
e achando tudo
Primeiro precisamos nos certificar que
as
placas estão devidamente
conectadas. Verifique isso executando o comando abaixo como root:
# lspci | grep VGA
00:0a.0 VGA compatible controller: (FABRICANTE / MARCA)
00:0b.0 VGA compatible controller: (FABRICANTE / MARCA)
Cada linha corresponde a uma placa do seu computador. O
primeiro campo corresponde a identificação do barramento
pci. Anote
estes endereços para configurar o servidor X.
Agora edite o arquivo /etc/X11/xorg.conf da seguinte maneira:
OBS: Note que os dispositivos recebem endereço BusID em decimal
e o
lspci mostra em hexa-decimal, para isto, substituir a por 10, b por 11
e assim por diante... preciso também conhecer previamente qual
driver
adequado para cada placa.
Section
"Device"
Identifier "Device
1"
Driver "vesa"
# vai depender do driver da sua placa
de
vídeo
BusID
"PCI:0:10:0"
EndSection
Section "Device"
Identifier "Device
2"
Driver "vesa"
# vai depender do drvier da sua placa
de
vídeo
BusID
"PCI:0:11:0"
EndSection
Section "Monitor"
Identifier "Monitor
X"
EndSection
Section "Monitor"
Identifier "Monitor
Y"
EndSection
Section "Screen"
Identifier "Screen
X"
Device "Device
1"
Monitor "Monitor X"
DefaultDepth 16
SubSection "Display"
Depth
16
Modes
"1024x768"
EndSubSection
EndSection
Section "Screen"
Identifier "Screen
Y"
Device "Device
2"
Monitor "Monitor Y"
DefaultDepth 16
SubSection "Display"
Depth
16
Modes
"1024x768"
EndSubSection
EndSection
Section "ServerLayout"
Identifier "Layout"
Screen "Screen
X"
Screen "Screen
Y" Below "Screen X"
InputDevice
"Keyboard1"
InputDevice
"Mouse1"
Option "DontZap"
"on" # evita que o usuário derrube o X
com ctrl alt backspace
Option "DontVTSwitch" "on"
# evita que o usuário troque
os vts
Option "BlankTime"
"0"
Option "StandbyTime"
"0"
Option "SuspendTime"
"0"
Option "OffTime"
"0"
EndSection
Aqui a configuração está feita para dois
terminais. Para fazer com mais é só usar a mesma coisa,
mas com vários
devices, vários monitores, vários screens. Se não
conseguir editar o
arquivo, use o
xorgcfg.
Agora execute o X e teste se abre todos os monitores. Se não,
volte a
configuração do X. Esta parte não deve ser
complicada, pois o próprio
configurador deve fazer.
Depois renomeie e mova o arquivo com os comandos:
# mv multiXnest-0.1.3 /usr/local/bin/multiXnest
# mv multiXnest.sh /usr/sbin/
Para verificar se os dispositivos estão devidamente conectados,
execute:
# cat /proc/bus/input/devices
Então olhe em cada seção se está plugado o
dispositivo. Agora vem a parte automática e legal.
Execute o script veevent.sh que está linkado na primeira
página e descubra qual o event de cada dispositivo.
Edite o arquivo
/etc/X11/gdm/gdm.conf na seção
"Servers":
[servers]
0=Principal
1=Xnest1
2=Xnest2
[server-Principal]
name=Principal
command=/usr/X11R6/bin/X
handled=false # faz com que este servidor
não seja usado para login
flexible=false
[server-Xnest1]
name=Xnest1
command=/usr/sbin/multiXnest.sh
-display :0.0 -xauthority /var/lib/gdm/:0.Xauth -geometry 1024x768+0+0
-kbd /dev/input/event0 -ptr /dev/input/event1 -dpi 92
handled=true
flexible=false
[server-Xnest2]
name=Xnest2
command=/usr/sbin/multiXnest.sh -display :0.1 -xauthority
/var/lib/gdm/:0.Xauth -geometry 1024x768+0+0
-kbd /dev/input/event2 -ptr /dev/input/event5 -dpi 92
handled=true
flexible=false
Agora mude event0, event1, event2, event5 pelos valores que você
descobriu no veevent.sh. Para cada terminal mude o valor do display
0.X.
Agora é só configurar o GDM no boot e usar.
O
MultiXnest possui alguns probleminhas de
visualização, menus
do qt e etc.. A aceleração 3D por exemplo é
desabilitada. Mesmo assim
esta solução eu considero bem melhor que a anterior (
MultiHeads
no Linux)
Exemplos de uso
Muitos laboratórios já foram montados
dessa forma. A redução de custos
gira em torno de 50% visto que os monitores ainda são uma
parcela
expressiva.
No departamendo de informática da UFPR os
multiterminais rodam como
servidores remotos sem HD. Então as máquinas não
são responsáveis por
imprimir uma tela somente, mas 4 telas de uma vez só. Por sua
vez cada
máquina dessa não processa nada localmente.