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