Espacio de tecnologia, software libre y sus derivados. Una horda de monos entrenados escriben de vez en cuando por aqui algunas noticias, opiniones e incluso alguna que otra cosa fuera del tema. Maqueros, favor de abstenerse que no somos lo suficientemente guapos.

Piano daemon

Archive for May, 2009

Compilar un nuevo kernel de NetBSD

Siempre es mejor compilar nuestro propio kernel BSD porque obtendremos uno más esbelto y rápido que el genérico que viene en la instalación. Bien, de manera rápida y sucia esta es la receta:

# cd /usr/
# wget -c http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/tar_files/src/sys.tar.gz

Nos movemos al directorio según la arquitectura, en este caso i386:

# cd /usr/src/sys/arch/i386/conf/
# cp GENERIC MYPLAUCHUKERNEL

Ahora debemos editar las opciones del kernel.

# nano ./MYPLAUCHUKERNEL

Ejecutamos config para generar las directivas de compilacion para nuestro nuevo kernelito bsdero.

# config MYPLAUCHUKERNEL
# cd ../compile/MYPLAUCHUKERNEL
# make depend &&  make

Renombramos el viejo kernel que está en raíz:
# mv /netbsd /netbsd.anterio.bak

Movemos el nuevo kernel a raíz:
# mv netbsd /

Y ya podemos bootear con nuestro nuevo kernel:

# reboot

La certificacion Java funciona ?

La certificacion Java funciona ?

Tuberias en LINUX

    #include "stdio.h"
    #include "stdlib.h"
    #include "errno.h"
    #include "unistd.h"

    int main(){

	//Aqui se define STDIN como el elemento 0 del arreglo pfds
	//Aqui se define STDOUT como el elemento 1 del arreglo pfds
	//Aqui se define STDERR como el elemento 2 del arreglo pfds
        int pfds[2];

	// Establecemos un buffer de 30 bytes
        char buf[30];

	//Creamos la tuberia
        if (pipe(pfds) == -1) {
            perror("pipe");
            exit(1);
        }

        printf("Escribiendo sobre el file descriptor de STDOUT");
        write(pfds[1], "Edwin", 5);
        printf("Lellendo sobre el file descriptor de STDIN");
        read(pfds[0], buf, 5);
        printf("Valor transportado en nuestra tuberia: \"%s\"n", buf);
    }

pipe1.gif

Basicamente, una llamada a pipe() retorno un par de file descriptors.

Nodos (Administracion de la Memoria Virtual en linux)

Aqui les dejo otra explicacion mas de la administracion de la memoria virtual en linux…
Antes deberas leer esto si no sabes que ondas con lo que pongo aqui

Cada no es representado por pg_data_t, el cual es un tipo definido para la estructura pglist_data. Cuando se asigna una pagina, Linux usa una politica de asignar memoria del nodo mas cercano a la CPU. A razon de que el proceso corre sobre la misma CPU,
es mas razonable que la memoria del actual nodo(o banco de memoria) sea la que se use. La estructura es declara como sigue en :

 typedef struct pglist_data {
       zone_t node_zones[MAX_NR_ZONES];
       zonelist_t node_zonelists[GFP_ZONEMASK+1];
       int nr_zones;
       struct page *node_mem_map;
       unsigned long *valid_addr_bitmap;
       struct bootmem_data *bdata;
       unsigned long node_start_paddr;
       unsigned long node_start_mapnr;
      unsigned long node_size;
     int node_id;
     struct pglist_data *node_next;
 } pg_data_t;

Bien, ahora describiremos cada uno de los nodos de esta estructura:

node_zones : La zonas para este nodo son ZONE HIGHMEM, ZONE NORMAL, ZONE DMA.

node_zonelists : Este es el orden de las zonas asignadas proveniente de build_zonelists() en mm/page alloc.c , este orden se establece cuando se llamo a free_area_init_core(). Una asignacion fallida en ZONE HIGHMEM puede mandar de regreso a ZONE NORMAL o de regreso a ZONE DMA.

nr_zones : Este es el numero de zonas sobre este nodo, entre uno y tres. No todos los nodos llegaran a tener 3.

node_mem_map Esta es la primera pagina del arreglo de structuras page que representan cada cuadro fisico en el nodo. Es sera acomodado en algun lugar dentro del global mem_map_array.

valid_addr_bitmap : Este es un mapa de bits que describe huecos en el nodo de memoria. En realidad este solo es usado para SPARC.

node_size : Numero total de paginas en esta zona.

node_id : Esta es la ID del nodo (NID).

node_next : Puntero a el siguiente nodo sobre una lista terminada en NULL.

bdata : Este es solo del interes del asignado de memoria de arranque ( boot memory ), hablaremos de el despues.

node_start_paddr : Esta es la principal direccion fisica del nodo.

node_start_mapnr : Este otorga el offset de la pagina dentro del mapa global de memoria (mem_map). Este es calculado en free_area_init_core() , el cual calcula el numero de paginas entre mem_ map y el mem_map local para este nodo llamado lmem_map.

Todos los nodos en el sistema son mantenidos sobre una lista llamada pgdat_list. Los nodos son albergados sobre una lista, como estos van siendo inicializados por la funcion init_bootmem_core().

En los nucleos de linux mas recientes a 2.2, un macro for_each_pgdat(), el cual es trivialmente definido como un loop for, es puesto para mejorar la legilbilidad del codigo.

Hilos con C (Compilado en Linux)

Aqui les muestro como compilo un programita para ejemplificar el uso de hilos

[j4nusx@localhost ~]$ gcc hilos.c -lpthread -Wall -o hilos
[j4nusx@localhost ~]$ ./hilos
En Funcion main: Creando el Hilo 0
En Funcion main: Creando el Hilo 1
En Funcion main: Creando el Hilo 2
En Funcion main: Creando el Hilo 3
En Funcion main: Creando el Hilo 4
Hola esto se ejecuta en el hilo #0!
Hola esto se ejecuta en el hilo #1!
Hola esto se ejecuta en el hilo #2!
Hola esto se ejecuta en el hilo #3!
Hola esto se ejecuta en el hilo #4!

Aqui el codigo fuente

#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"
#define NUM_THREADS     5

// La funcion que es utilizada en un Hilo
// debera de retornar un puntero sin tipo
void *ImprimeSaludo(void *threadid){
   long tid;
   // Aqui se castea lo que le fue pasado
   // al hilo como atributos
   tid = (long)threadid;
   printf("Hola esto se ejecuta en el hilo #%ld!n", tid);
   pthread_exit(NULL);
}
// --- Aqui finaliza la funcion que
// sera llamada en el hilo

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t < NUM_THREADS; t++){
      printf("En Funcion main: Creando el Hilo %ldn", t);
      rc = pthread_create(&threads[t], NULL, ImprimeSaludo, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %dn", rc);
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

La función que nos permite crear un un nuevo hilo de ejcución es pthread_create() que admite cuatro parámetros:


pthread_t * es un puntero a un identificador de thread. La función nos devolverá este valor relleno, de forma que luego podamos referenciar al hilo para “hacerle cosas”, como matarlo, esperar por él,etc.
pthread_attr_t * son los atributos de creación del hilo. Hay varios atributos posibles, como por ejemplo la prioridad. Un hilo de mayor prioridad se ejecutará con preferencia (tendrá más rodajas de tiempo) que otros hilos de menor prioridad. Se puede pasar NULL, con lo que el hilo se creará con sus atributos por defecto y para nuestro ejemplo es suficiente. Si queremos un programa que cree y destruya hilos continuamente, no vale NULL, ya que con esta opción dejaremos memoria sin liberar cada vez que termine un hilo.
void *(*)(void *) es un tipo la mar de raro. Aunque asuste, no es más que el tipo de una función que admite un puntero void * y que devuelve void *. Eso quiere decir que a este parámetro le podemos pasar el nombre de una función que cumpla lo que acabamos de decir. Esta función es la que se ejecutará como un hilo aparte. El hilo terminará cuando la función termine o cuando llame a la función pthread_exit() (o que alguien lo mate desde otra parte del código). Es bastante habitual hacer que esta función se meta en un bucle infinito y quede suspendida en un semáforo o a la espera de una señal para hacer lo que tenga que hacer y volver a quedar dormida.
void * es el parámetro que se le pasará a la función anterior cuando se ejecute en el hilo aparte. De esta manera nuestro programa principal puede pasar un único parámetro (que puede ser cualquier cosa, como una estructura compleja) a la función que se ejecutará en el hilo. La función del hilo sólo tendrá que hacer el “cast” adecuado.

La función pthread_create() devuelve 0 si todo ha ido bien. Un valor distinto de 0 si ha habido algún problema y no se ha creado el thread.

Si deseas saber mas a detalle el asunto de los hilos en linux, te recomiendo la siguente liga

Relacion entre nodos, zonas y paginas (Administracion de la Memoria Virtual en linux)

Linux esta disponible para una gran gama de computadores, y a causa de esto, los desarrolladores encontraron una manera independiente a la arquitectura para describir lo que es la memoria.

CONCEPTOS QUE PREVALECEN EN LA ADMINISTRACION DE MEMORIA VIRTUAL (VM)

NUMA: Forma no uniforme de acceso a la memoria.

Bancos de MEmoria

En Maquina grandes la memoria puede ser agrupada en bancos de memoria, cada uno de estos bancos puede ser asignado a un CPU o a un DMA.

Cada banco de memoria es llamado NODO.

Un nodo en linux es representado por la estructura “pglist_data“, aun si la arquitectura es UMA.

UMA: Acceso Uniforme a memoria.
La Estructura “pglist_data” es siempre referenciada mediante su tipo “pg_data_t“.

Cada NODO en el sistema es albergado sobre una lista terminada en NULO, cuyo nombre es “pgdat_list” y cada nodo es linkeado al siguiente con el campo pg_data_t->node_next.

Para arquitecturas UMA (Las pcs de escritorio son de este tipo de arquitectura), solo existe una estructura estatica “pg_data_t” llamada “contig_page_data” que es usada.

Cada banco de memoria o NODO, es dividido en bloques llamados zonas. Las zonas representan rangos dentro de la memoria.

La Zona es definida por la estructura “zone_struct“, pero es siempre referenciada mediante el tipo de dato definido “zone_t“.
Las zonas pueden ser de 3 tipos:


- DMA
- NORMAL
- HIGHMEM

ZONA_DMA: Memoria en rangos bajos de memoria fisica, requerida por los dispositivos ISA.
ZONA_NORMAL: Ubicada en la posicion alta del espacio lineal de direcciones.
ZONA_HIGHMEM: Memoria restante en el sistema y no es directamente mapeada por el kernel.

La memoria del sistema es agrupada en lotes llamados “page frames“, Cada “page frame” es representado por la estructura “page” y todas las estructuras son mantenidas en un arreglo global llamado “mem_map“, el cual es usualmente almacenado al inicio de la ZONA_NORMAL o del area reservada para la imagen del kernel cargada en maquinas de poca memoria.

Relacion entre nodos, zonas y paginas (Administracion de la Memoria Virtual en linux)

Antipatrones de Diseño

Antipatrones de diseño…. Huy muchos de estos operan en mi lugar de trabajo :p

Conoce a los creadores de C

25 años de UNIX…



No cabe duda que UNIX es lo mejor….
Para ver el video en pantalla completa… acciona el boton HQ

Punteros a funciones .. para que sirve ?

Aqui la misterioza y clara manera de usar punteros a funciones

#include "stdio.h"

void printMensaje (float dato);
void printNumero (float dato);
void (*funcPuntero)(float);

int main()
{
  float pi = 3.14159;
  printMensaje(pi);
  funcPuntero = printMensaje;
  funcPuntero (pi);
  funcPuntero = printNumero;
  funcPuntero (pi);
  printNumero(pi);
  return 0;
}

void printMensaje(float dato)
{
  printf(" Esta es la funcion printMensaje %f",dato);
}

void printNumero(float dato)
{
  printf("Esta es la funcion print %f", dato);
}

Punteros a funciones .. para que sirve ?
Por que no le preguntan a la gente de .NET y sus delegados.

« Entradas anteriores