console.cy keyboard.c - La web de Sistemas Operativos (SOPA)

Transcripción

console.cy keyboard.c - La web de Sistemas Operativos (SOPA)
console.c y keyboard.c
Manejador de consola y de teclado.
Francisco Jesús Santana Jorge
1
Contenido:
z Introducción
a los terminales.
z Organización en el núcleo y estructuras
de datos principales.
z Introducción al directorio drivers.
z Fichero console.c
z Fichero keyboard.c
z Apendice.
2
Introducción.
¿Qué es un terminal?
Un terminal es cada dispositivo que
permite a un usuario interactuar con una
máquina.
En Linux, nos podemos encontrar una
una gran cantidad de terminales, los
cuales los podemos clasificar en cuatro
tipos.
3
Introducción.
Tipos de terminal: Son los siguientes:
-
-
Consolas virtuales: usadas cuando el usuario se
conecta físicamente a la máquina.
Pseudoterminales: se emplean para simular un
terminal. Se implementan usando una pareja de
dispositivos especiales y distintos denominados
esclavo y maestro.
Puertos serie: utilizados por los módems o el
ratón.
Terminales particulares: la consola, las tarjetas
serie específicas y ciertos ratones PS/2.
4
Introducción.
Se puede distinguir dos modos de uso de un terminal:
-
-
Modo canónico: donde la entrada de un terminal se
gestiona en forma de líneas, es decir, que un programa
que quiera leer de una terminal deberá esperar hasta que
se introduzca una línea completa.
Modo no canónico: los caracteres en entrada no se tratan
en forma de línea. Se emplean los valores MIN y TIME
para determinar la manera de como se reciben los
caracteres,
MIN: indica el nº mínimo de caracteres que deben
recibirse antes de que la lectura se satisfecha.
TIME: es un timer en décimas de segundo que se utiliza
para hacer accesibles los datos tras un cierto lapso de
tiempo.
5
Introducción.
Existen cuatro comportamientos particulares
MIN > 0 Y Si MIN caracteres se reciben antes de TIME entonces se satisface
TIME > 0 la lectura, sino los caracteres recibidos se devuelven al usuario.
Si el nº de caracteres leídos es inferior a los disponibles, entonces
el timer no se reactiva y la lectura siguiente se satisface
inmediatamente.
MIN > 0 Y Una lectura solo se satisface cuando se han recibido MIN
TIME = 0 caracteres.
MIN = 0 Y Una lectura se satisface cuando se recibe un solo carácter, a
TIME > 0 menos que transcurra la duración.
MIN = 0 Y Se devuelve el número mínimo de caracteres solicitados.
TIME = 0
6
Organización en el núcleo y
estructuras de datos principales.
Los terminales pueden considerarse como una interfaz
lógica entre los datos y el material que debe transmitirse
a través de un dispositivo cualquiera como una línea
serie, un ratón, una impresora o incluso la consola de la
máquina de un usuario.
7
Organización en el núcleo y
estructuras de datos principales.
8
Organización en el núcleo y
estructuras de datos principales.
9
Introducción al directorio drivers.
Este directorio se localiza en el código fuente del
núcleo de Linux y contiene todas las rutinas que
implementan las funcionalidades de los distintos
dispositivos que maneja Linux.
De de este directorio, nos intereza el
subdirectorio char que contiene los fuentes de
los drivers que maneja el teclado y la pantalla.
10
Introducción al directorio drivers.
11
Fichero console.c
Define el tipo de terminal de Linux, especificando las secuencias de
escape y codificación del teclado
12
Fichero console.c
13
Fichero console.c
Inicialización de la consola: La inicialización
de la consola es realizada por la función
tty_init() que se encuentra en tty_io.c, el cual es
el encargado de gestionar todas las
entradas/salidas de alto nivel sobre los
terminales.
La función tty_init() inicializa los terminales (tty)
de la máquina y se encarga de conseguir el
número mayor asignado al dispositivo y de
llamar al función init de cada dispositivo
asignado, en nuestro caso el con_init() que se
encuentra en console.c.
14
Fichero console.c
15
Fichero console.c
¿Cómo lo hace?
16
Fichero console.c
¿Cómo lo hace?
17
Fichero console.c
¿Cómo lo hace?
18
Fichero console.c
Escritura en la consola: Cuando en un
dispositivo de consola se esta escribiendo, la
función con_write() es invocada.
Esta función maneja todos los caracteres de
control y secuencia de escape empleados para
proveer de aplicaciones con un manejo
completo de la pantalla.
La función con_write() se compone sobre todo
de selectores, usados por un autómata finito
para interpretar las secuencias de escape o un
carácter a la vez.
19
Fichero console.c
static int con_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
int retval;
pm_access(pm_con);
retval = do_con_write(tty, from_user, buf, count);
con_flush_chars(tty);
return retval;
}
20
Fichero console.c
21
Fichero console.c
La función do_con_trol() se encarga de procesar los
caracteres que no mostrables por pantalla, como son
BELL(genera un pitido), BS(Backspace, mueve el cursor
a la izquierda la posición de un carácter), LF(Lines feed,
genera una nueva línea)…
switch (c) {
case 0:
return;
case 7:
if (bell_duration)
kd_mksound(bell_pitch, bell_duration);
return;
case 8:
bs(currcons);
return;
22
Fichero console.c
23
Fichero keyboard.c
En líneas generales lo que hace el keyboard.c es:
Cuando una tecla es presionada, el controlador de teclado
envía scancodes, códigos de rastreo del teclado, al driver
del teclado (keyboard.c).
El núcleo cuando recibe los scancodes realiza una
traducción a un código interno denominado keycodes que
luego se le pasa al keymap para que este devuelva el
carácter o la secuencia encontrada o la acción descrita allí
a el programa de usuario.
24
Fichero keyboard.c
Los keymap son mapas de caracteres empleados para
determinar el código de carácter que se le pasa a la
aplicación basándose en la tecla que ha sido pulsada y
los modificadores activos en ese momento.
Puede haber varios keymaps y la razón de esto es que
no todos los lenguajes poseen los mismos caracteres y
símbolos de puntuación.
25
Fichero keyboard.c
Lo anterior lo realiza la rutina handle_scancode. La
rutina handle_scancode recibe los scancodes y los
convierte en keycodes.
… … …
if (!kbd_translate(scancode, &keycode, raw_mode))
goto out;
… … …
y luego los pasa al keymap:
… … …
if (key_map != NULL) {
keysym = key_map[keycode];
… … …
26
Apendice: struct consw
struct consw {
const char *(*con_startup)(void);
void (*con_init)(struct vc_data *, int);
void (*con_deinit)(struct vc_data *);
void (*con_clear)(struct vc_data *, int, int, int, int);
void (*con_putc)(struct vc_data *, int, int, int);
void (*con_putcs)(struct vc_data *,const unsigned short *,int ,int ,int);
void (*con_cursor)(struct vc_data *, int);
int
(*con_scroll)(struct vc_data *, int, int, int, int);
void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
int
(*con_switch)(struct vc_data *);
int
(*con_blank)(struct vc_data *, int);
int
(*con_font_op)(struct vc_data *, struct console_font_op *);
int
(*con_set_palette)(struct vc_data *, unsigned char *);
int
(*con_scrolldelta)(struct vc_data *, int);
int
(*con_set_origin)(struct vc_data *);
void (*con_save_screen)(struct vc_data *);
u8
(*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8);
void (*con_invert_region)(struct vc_data *, u16 *, int);
u16 *(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
};
27
Apendice: struct console
struct console{
char name[8]; /* indica el nombre del dispositivo de la consola. */
/* función que entre otras cosas se usa para imprimir los mensajes del núcleo. */
void (*write)(struct console *, const char *, unsigned);
/* función que realiza la lectura de datos de la consola. */
int
(*read)(struct console *, const char *, unsigned);
/* función que retorna el número del dispositivo para el dispositivo terminal que
actualemente esta actuando como consola. */
kdev_t (*device)(struct console *);
/* función que fuerza un delay hasta que el usuario presiona una tecla. */
int
(*wait_key)(struct console *);
/* esta función es opcional y define una operación unblank sobre la pantalla. */
void (*unblank)(void);
int
(*setup)(struct console *, char *);
short flags; /* varios flags para el control de la consola. */
short index;
int
cflag;
struct console *next;
};
28
Apendice: struct console_cmdline.
struct console_cmdline{
char name[8]; /* Nombre del driver.
*/
int index;
/* Menor disp. a usar
*/
char *options; /* Opciones para el driver */
};
29
Apendice: struct tty_struct
struct tty_struct {
/*nº mágico que identifica la estructura TTY_MAGIC.*/
int magic;
/*interfaz de acceso al dispositivo asociado al terminal.*/
struct tty_driver driver;
/*interfaz para la disciplina de la línea.*/
struct tty_ldisc ldisc;
/* bloqueo de la configuración del terminal. Si este
campo vale NULL, la configuración no esta
boqueada.*/
struct termios *termios, *termios_locked;
int pgrp; /*identificador del grupo de procesos.*/
30
Apendice: struct tty_struct
int session; /*número de sesión. */
/*nº del disp. obtiene los nº mayor y menor del disp.*/
kdev_t device;
unsigned long flags; /*indica el estado del terminal.*/
/*nº de aperturas que se han efectuado en el terminal.*/
int count;
struct winsize winsize; /*tamaño de la ventana.*/
unsigned char stopped:1; /*indica terminal bloqueado.*/
/*utilizado en los gestores de bajo nivel para indicar que
el dispositivo está en un estado (temporal) no
disponible.*/
unsigned char hw_stopped:1;
31
Apendice: struct tty_struct
unsigned char flow_stopped:1;
unsigned char packet:1; /*modo paquete.*/
unsigned char low_latency:1, warned:1;
/*tipo de control para el modo paquete.*/
unsigned char ctrl_status;
/*lista encadenada de terminales utilizada
para los pseudoterminales.*/
struct tty_struct *link;
/*estructura que utiliza ciertas estructruras de datos
definidas en el sistema de archivos.*/
struct fasync_struct *fasync;
32
Apendice: struct tty_struct
/*memoria intermedia de datos que deben enviarse a la
disciplina de la línea.*/
struct tty_flip_buffer flip;
int max_flip_cnt; /*no se usa.*/
/*empleada para cambiar la velocidad del terminal.*/
int alt_speed;
/*lista de procesos en espera de escritura.*/
wait_queue_head_t write_wait;
/*lista de procesos en espera de lectura.*/
wait_queue_head_t read_wait;
struct tq_struct tq_hangup;
void *disc_data; /*no se usa*/
33
Apendice: struct tty_struct
/*puntero genérico utilizado para manipular una
estructura de datos propia del dispositivo.*/
void *driver_data;
struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096
/*Los campos siguientes se usan para la disciplina de
lalínea. Por razones históricas, estos datos se incluyen
en esta structura.*/
unsigned int column; /*nº columnas de la ventana.*/
34
Apendice: struct tty_struct
/*gestión:
- carácter LNEXT.
- supresión de un carácter.
- modo raw.
- modo no canónico.
*/
unsigned char lnext:1, erasing:1, raw:1, real_raw:1,
icanon:1;
/*rechazo de carácter esperando generalmente que los
carácters hayan sido transmitidos correctamente al
dispositivos*/
unsigned char closing:1;
35
Apendice: struct tty_struct
/*tiempo minimo restante antes de desencadenar el
timer en el caso en que se use el modo canónico.*/
unsigned short minimum_to_wake;
unsigned overrun_time; /*duración del desbordamiento*/
/*nº de situaciones de desbordamiento encontradas*/
int num_overrun;
/*se trata de una tabla de bytes que permite saber si los
caracteres están definidos.*/
unsigned long
process_char_map[256/(8*sizeof(unsigned long))];
char *read_buf; /*memoria de entrada circular.*/
int read_head; /*índice del primer carácter no leído.*/
36
Apendice: struct tty_struct
int read_tail; /*índice del último carácter no leído*/
/*nº de caracteres en la memoria intermedia.*/
int read_cnt;
/*se trata de una tabla que indica si una línea situada en
la tabla read_buf es legible o no*/
unsigned long
read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned
long))];
int canon_data; /*nº de líneas a punto para ser leídas*/
unsigned long canon_head; /*índice del primer carácter
de la primera línea en read_buf*/
37
Apendice: struct tty_struct
/*utilizado en el formateo de los datos para la salida:
representa el número de la columna del próximo carácter
a insertar.*/
unsigned int canon_column;
/*semáforo que controla la lectura.*/
struct semaphore atomic_read;
/*semáforo que controla la escritura.*/
struct semaphore atomic_write;
spinlock_t read_lock;
struct tq_struct SAK_tq;
};
38
Apendice: struct tty_driver
struct tty_driver {
int magic; /* número mágico que identifica la estructura */
const char *driver_name; /* nombre del driver. */
const char *name; /* nombre del dispositivo. */
/* desplazamiento para acceder al nombre del términal */
int name_base;
/* número mayor del dispositivo */
short major;
short minor_start; /* inicio del número menor del dispositivo */
/* number of devices */
short num;
/* tipo del gestor de dispositivo del terminal.*/
short type;
short subtype;
/* subtipo del gestor del terminal */
struct termios init_termios; /* inicialización del terminal. */
/* estados y opciones del terminal */
int flags;
int *refcount;
/* para cargar los drivers tty */
39
Apendice: struct tty_driver
struct proc_dir_entry *proc_entry; /* para la entrada /proc fs */
/* usado únicamente por los pseudoterminales */
struct tty_driver *other;
/* Puntero a las estructuras de datos tty */
/* lista de terminales vinculados a este dispositivo */
struct tty_struct **table;
struct termios **termios; /* lista de termios de los terminales. */
/* lista de termios bloqueados de los terminales */
struct termios **termios_locked;
void *driver_state; /* únicamente usada para los drivers PTY */
/* se abre un nuevo terminal. Si esta función falla, devuelve el error
ENODEV */
int (*open)(struct tty_struct * tty, struct file * filp);
/* se cierra un dispositivo. */
void (*close)(struct tty_struct * tty, struct file * filp);
40
Apendice: struct tty_driver
/* Debe escribir un cierto número de caracteres en el dispositivo. Los caracteres
pueden provenir del espacio de usuario(from_user) o bien del espacio del núcleo.
Devuelve el número de caracteres que se han aceptado para la escritura. */
int (*write)(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count);
/* Debe escribir un carácter en el dispositivo. Si el núcleo utiliza esta rutina, debe
llamar a la función flush_chars si está definida. Si no hay espacio en la memoria
intermedia, el carácter se ignora. */
void (*put_char)(struct tty_struct *tty, unsigned char ch);
/* Se llama después de haber escrito un cierto número de caracteres en el dispositivo
con put_char. */
void (*flush_chars)(struct tty_struct *tty);
/* Devuelve el número de carácteres que el dispositivo acepta recibir(en memoria
intermedia) para su escritura. Este número puede cambiar a medida que se llenan
las memorias intermedias, o si el control del flujo está activo.
int (*write_room)(struct tty_struct *tty);
41
Apendice: struct tty_driver
/* Devuelve un valor diferente de 0 si se encuentran caracteres en la
memoria 100 intermedia. */
int (*chars_in_buffer)(struct tty_struct *tty);
/* Permite que el gestor de dispositivos implemente la llamada ioctl
para el dispositivo. Si el parámetro cmd no se gestiona o no es
reconocido por el gestor, la función devuelve el error
ENOIOCTLCMD. */
int (*ioctl)(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
/* Se llama para advertir al gestor cuando la configuración (termios)
de un dispositivo ha sido modificada. Resulta útil destacar que los
gestores bien diseñados deberían gestionar el caso en que old
contenga el valor NULL e intentar hacer algo racional en ese caso.
*/
void (*set_termios)(struct tty_struct *tty, struct termios * old);
42
Apendice: struct tty_driver
/* Las memorias de salida para la disciplina de la línea están casi
llenas. El gestor debería señalar a los procesos que escriben que no
debería enviarse ningún carácter más al terminal. */
void (*throttle)(struct tty_struct * tty);
/* Indica al gestor de dispositivo que debería señalar que pueden
enviarse datos al terminal sin temor a desbordar la memoria
intermedia de disciplina de la línea. */
void (*unthrottle)(struct tty_struct * tty);
/* Indica al gestor que debería dejar de enviar caracteres al
dispositivo. */
void (*stop)(struct tty_struct *tty);
43
Apendice: struct tty_driver
/* indica al gestor que puede, si lo desea, emitir o reenviar
caracteres en el dispositivo. */
void (*start)(struct tty_struct *tty);
/* El gestor debería cerrar el dispositivo. */
void (*hangup)(struct tty_struct *tty);
/* Esta rutina opcional pide al driver tty que se ponga en estado de
BREAK. */
void (*break_ctl)(struct tty_struct *tty, int state);
/* Debe vaciar las memorias intermedias. */
void (*flush_buffer)(struct tty_struct *tty);
/* Permite que el gestor de dispositivos sea advertido cuando la
configuración(termios) de un dispositivo ha cambiado. */
void (*set_ldisc)(struct tty_struct *tty);
44
Apendice: struct tty_driver
/* Esta rutina espera hasta que el dispositivo ha puesto todos los
caracteres en su transmisor FIDO. */
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
/* Esta rutina es usada para enviar un carácter de alta-prioridad
XON/XOFF al dispositivo. */
void (*send_xchar)(struct tty_struct *tty, char ch);
int (*read_proc)(char *page, char **start, off_t off, int count, int *eof,
void *data);
int (*write_proc)(struct file *file, const char *buffer, unsigned long
count, void *data);
struct tty_driver *next;
struct tty_driver *prev;
};
45
Apendice: struct tty_ldisc
struct tty_ldisc {
int magic; /* nº mágico que identifica a la estructura*/
char *name;
int num; /* Identificador de la línea*/
int flags; /* Tipo de línea*/
int (*open)(struct tty_struct *); /* Apertura de la línea.*/
void (*close)(struct tty_struct *); /* Cierre de la línea.*/
void (*flush_buffer)(struct tty_struct *tty);/*Vaciado memorias intermedias*/
/*Indica si hay caracteres presentes en la memoria. */
ssize_t (*chars_in_buffer)(struct tty_struct *tty);
ssize_t (*read)(struct tty_struct * tty, struct file * file,
unsigned char * buf, size_t nr); /* Lectura.*/
ssize_t (*write)(struct tty_struct * tty, struct file * file,
const unsigned char * buf, size_t nr); /*Escritura*/
46
Apendice: struct tty_ldisc
int
(*ioctl)(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg); /*Envío de una petición. */
/*Configuración de la línea.*/
void (*set_termios)(struct tty_struct *tty, struct termios * old);
unsigned int (*poll)(struct tty_struct *, struct file *,
struct poll_table_struct *);
/* Devuelve un puntero a la memoria intermedia de datos recibida.
*/
void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
char *fp, int count); int (*receive_room)(struct tty_struct *);
/* Número de caracteres en la memoria intermedia de salida. */
void (*write_wakeup)(struct tty_struct *);
};
47