jueves, 15 de diciembre de 2011

[S.O] Agregando un System Call a MINIX 3 [Programación]



Comencemos por explicar que es una llamada al sistema:

Las llamadas al sistema comúnmente usan una instrucción especial de la CPU que causa que el procesador transfiera el control a un código privilegiado, previamente especificado por el mismo código. Esto permite al código privilegiado especificar donde va a ser conectado así como el estado del procesador.

Para que esto funcione se utilizan librerías como intermediarias.
los sistemas operativos proveen bibliotecas que relacionan los programas de usuario y el resto del sistema operativo, usualmente una biblioteca C como glibc o el runtime de Microsoft C.

Para este pequeño laboratorio utilice la distribucion de Minix 3.1.8 actual para ser exacto esta: minix_R3.1.8-r8398.iso.bz2 (288 MB) 

Preparando el ambiente para comenzar a programar la llamada al sistema.

Una vez que tenemos todo eso listo, manos a la obra:
/***Recomiendo utilizar un editor como vim o nano (instalar vim: pkgin install vim) para crear y modificar los archivos en Minix esto por los inconvenientes que presenta en algunos casos trabajar con eclipse desde windows ya que le agrega caracteres al final de cada linea***/

1-) Agregamos el código de nuestra llamada al VFS task

Este es el código que formara parte del kernel y se ejecutara cuando se invoque el system call. Escribir el código de la función do_holamundo() y agregarla al archivo /usr/src/servers/vfs/misc.c


PUBLIC int do_holamundo()
{
printf("Hola Mundo.\n");
printf("Use your imagination...\n");
return(OK);
}




2-) Abrimos el archivo callnr.c que se encuentra en /usr/src/include/minix


Incrementar en uno la cantidad de system calls permitidos y definir un
numero que identificara para la llamada holamundol().



En la primera linea encontramos esto:

#define NCALLS 113 /*113  number of system calls allowed */

Gracias a el comentario sabemos lo que hace, ok por logica y como vamos a agregar un system call mas entonces le agregamos uno mas quedando en 114 asi:

#define NCALLS  114 /*114  number of system calls allowed */

En este mismo archivo buscamos la linea:

#define GCOV_FLUSH 112 /* flush gcov data from server to gcov files */

y agregamos nuestra definicion en la siguiente linea:

#define HOLAMUNDO 113

3-) Abrimos el archivo proto.h que se encuentra en /usr/src/servers/vfs
Buscamos el bloque de  /* misc.c */
y al final agregamos:

_PROTOTYPE( int do_holamundo, (void) );

*Antes de /* mount.c */

4-) Indicar a la tarea de VFS que debe invocar la función do_holamundo() cada vez que se intente acceder a la llamada numero 113. Modificar /usr/src/servers/vfs/table.c y agregar:

do_holamundo, /* 113 = HOLAMUNDO */


5-) Indicar a la tarea PM que debe invocar la función no sys() cada vez que se intente acceder a la llamada numero 113. La función no sys() retorna un código de error indicando que se intento utilizar un servicio que no brinda la tarea. Modificar /usr/src/servers/pm/table.c y agregar:

no_sys, /* 113 = HOLAMUNDO */



Compilar el código del kernel que acabamos de modificar, ejecutar como el usuario root los siguientes comandos:

# cd /usr/src/tools
# make image
#make install
# make hdboot
# reboot

Ahora listo ya modificamos el kernel y agregamos nuestra llamada al sistema pero como podemos saber que funciona?
R//= Creamos un programita en C que la invoque.


Crear el archivo hellocall.c que contenga:


Notar que el llamado a syscall() toma como parámetro un mensaje (dummy_msg), ese mensaje es enviado al kernel y se lo puede acceder desde las funciones implementadas dentro del kernel como ser do_holamundo(). De esa manera se pueden enviar datos desde los programas de usuario a las funciones que corren desde el kernel:


#include <lib.h>
#define holamundo _holamundo
#include <unistd.h>
PUBLIC int holamundo(void)
{
message dummy_msg;
return(_syscall(VFS_PROC_NR,HOLAMUNDO,&dummy_msg));
}


-Proveemos la declaracion de la función de librería. Escribir el archivo holamundo.h:


#ifndef _ANSI_H
#include <ansi.h>
#endif
_PROTOTYPE( int holamundo, (void) );



-Escribir el archivo mysyscall.s:

.sect .text
.extern __holamundo
.define _holamundo
.align 2
_holamundo:
jmp __holamundo


-Compilar los archivos cuyo código objeto formara nuestra librería, ejecutar como usuario root:

#cc -c ./_holamundo.c
#cc -c ./holamundo.s


Enlazar los archivos holamundo.o y _holamundo.o para crear nuestra librería libhello.a. El compilador de Minix busca las librerías en el directorio /usr/lib/i386 por lo que es necesario copiar nuestra librería a ese sitio.

Ejecutar como usuario root:

#aal cr ./libhello.a ./holamundo.o
#aal cr ./libhello.a ./_holamundo.o
#cp ./libhello.a /usr/lib/i386


Estamos en condiciones de invocar el nuevo system call que agregamos al kernel, para utilizarlo escribir el programa saludo.c:

#include "holamundo.h"
int main (void)
{
holamundo();
return(0);
}

Otra manera de invocar la llamada en C es asi:


#include<lib.h>
#include<unistd.h>

#define SYS_CALL_NUMBER 113 /*Donde 113 es el numero de llamada que agregamos*/
int main(void)
{
message m;
_syscall(1,SYS_CALL_NUMBER,&m);
return 0;

}


Compilamos el programa:

#cc test.c  -o test -l hello
Ejecutamos
#./test

En mi caso aca esta el resultado:






3 comentarios :

Anónimo dijo...

Sos un groso hermano!!!!! Muchas gracias por el tuto!!!

Unknown dijo...
Este comentario ha sido eliminado por el autor.
Unknown dijo...

Me gustaria saber como hacer esto

Implementar una llamada al sistema para que retorne el PID (Process ID) y el PPID (Parent Process ID) y que reciba como parámetro un nombre como valor y lo devuelva escrito al reves.

2- Agregar un archivo con entradas de usuario y contraseña y previo a mostrar el prompt (Shell hecho en clases) obligue al usuario a iniciar sesión.

3- Agregar el Shell a MINIX como parte del SO, es decir como otro Shell más.

4- Realice cualquier programa en C/C++ y ejecútelo desde el Shell.

Publicar un comentario

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Best Web Host