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().
#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 :
Sos un groso hermano!!!!! Muchas gracias por el tuto!!!
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