25
Jan
2014

Nvidia NVS 5400 (Optimus) propietary driver on Linux Mint 16

For about 6 months, since I’m using the Nvidia NVS 5400 (with Optimus technology) video card, I’ve been having weird random crashes at boot time. Optimus was disabled at UEFI and I tried many versions of the Nvidia closed drivers. This happened both in Linux Mint 15 and Linux Mint 16 and no kernel upgrade (at least for now) solved it.

I disabled nouveau and nvidia drivers and booted on plain text mode. What I noticed was a repetitive sequence of events: 1. grub started fine, 2. a video controlled was used by the kernel, 3. at some point, the video controller was switched for a new one and that was the moment of the random crash. If the system crashed, no log nor output was given: only a freeze (sometimes black) screen. I think this issue is in the new video controller, that doesn’t load well every time or can’t handle the nvidia chipset.

So, If you are stuck on this, what I did was editing the /etc/default/grub file replacing GRUB_CMDLINE_LINUX_DEFAULT var with the following: GRUB_CMDLINE_LINUX_DEFAULT=”video=vga text nvidia.blacklist=1 nomodeset”. Then you have to run updagrade-grub2. nomodeset does the trick: when we disable KMS (Kernel Mode-setting) system boots with a fallback/legacy video controller and no crashes. After booting, we log in using the command line interface, run startx and we are on desktop with nvidia drivers loaded.

Of course we won’t have a beautiful graphic splash boot screen but works like a charm! No crashes, no pain.

27
Oct
2012

Linux: analizando el stack de un proceso

En este breve artículo quiero presentar un análisis básico del stack de un proceso en Linux. Se trata de un caso de ejecución sencillo, contado como un storyboard, para ir a los conceptos fundamentales del código ejecutable (visto como assembler), llamadas a funciones y manejo de memoria. La arquitectura en este caso es IA-32.

1. Tenemos un programa sencillo escrito en C

#include <stdio .h>
#include <stdlib .h>
 
int main(void){
 
    int x;
    int y;
 
    x = 4;
    y = 5;
 
    foo();
 
    return 0;
}
 
int foo(){
    int y = 1;
    return y;
}
</stdlib></stdio>

Se declaran dos variables locales en la función main, se llama a una función foo y se declara una variable local en la función foo.


Leer el resto del artículo »

9
Sep
2012

Desde un High-Level Language a un archivo ejecutable

pasaje de high level language a archivo ejecutable assembler

Professional Assembly Language – Richard Blum (2005)

La figura describe el proceso que se desarrolla para traducir código escrito en un lenguaje de alto nivel (High-Level Language) a código de máquina (contenido en un archivo binario ejecutable).

El compilador cumple la función de transformar el código escrito en el lenguaje de alto nivel a código objeto. El código objeto es código de máquina que aún no se encuentra en condiciones de ser ejecutado, por las razones que veremos más adelante. Este código depende de la arquitectura de procesador para la cuál se compile (por ejemplo IA-32, ARM, etc.).

En lenguajes como C y C++, se suele generar un archivo de código objeto por cada archivo con código de alto nivel -contando los headers y su implementación en forma conjunta-.

La mayoría de los programas se componen de múltiples archivos con código de alto nivel. Existe una relación entre estos archivos para definir estructuras complejas, reutilización de componentes, separación de funcionalidades e interacciones.


Leer el resto del artículo »

6
Jul
2012

Charla de Linus Torvalds en la Universidad Aalto

Si tienen algo de tiempo, quiero recomendarles mirar esta charla de Linus Torvalds en la Universidad Aalto (Finlandia), realizada el 14 de junio de 2012. Básicamente son preguntas sobre los temas más variados que involucran al sistema operativo Linux y a los proyectos y comunidades open-source en general, realizadas por el entrevistador y por la audiencia.

Hay unas cuantas perlitas. No quiero adelantarles aquí nada porque es mejor verlo, pero les digo que no tiene desperdicio y Linus es un genio 🙂


Link directo: http://www.youtube.com/watch?v=MShbP3OpASA

Me dejó pensando como el tipo puede dedicarse con pasión a los aspectos técnicos del proyecto y dejar toda la basura del negocio y la gestión en manos de otros. ¿Cuáles son los motivos por los cuales nosotros deberíamos o no-deberíamos despreocuparnos, como profesionales de perfil técnico, de la basura del negocio y dedicarnos con pasión a lo que nos gusta? ¿El dinero? ¿La necesidad de irse a otro país? ¿Cuánto lo vale? ¿Puede uno, haciendo convivir ambas cosas, sentirse satisfecho a la larga?

22
Jun
2012

Modificar parámetros del kernel (Linux y BSD)

Los kernel de Linux y BSD tienen parámetros que pueden ser configurados para habilitar, deshabilitar o modificar ciertas funcionalidades. Estas funcionalidades pueden estar relacionadas al stack de comunicaciones, a la memoria virtual, a los medios de almacenamiento y al comportamiento del CPU entre otros.

Los parámetros -como es de suponer- tienen valores por defecto. Cuando el kernel inicia, inspecciona el archivo de configuración /etc/sysctl y los archivos contenidos en la carpeta /etc/sysctl.d/ para reemplazar los valores por defecto por los valores allí especificados. A su vez, durante la ejecución (o runtime), el kernel almacena los valores que se encuentra usando para estos parámetros en la estructura de carpetas /proc/sys. Dentro de esta estructura jerárquica hay archivos de texto con el nombre del parámetro y su valor.


Leer el resto del artículo »

12
May
2012

Forking de procesos en Linux

La creación de procesos en Linux implica dos etapas: forking y exec -me tomo la licencia de denominarlas así por las familias de funciones implicadas en cada caso-.

En la etapa de forking se duplica el proceso que realiza la llamada de creación. Para esta duplicación se crea un nuevo process descriptor -estructura donde se guarda la información del proceso- y se agrega a la lista de process descriptors que maneja el kernel. Este nuevo process descriptor es muy similar al del proceso padre pero difiere en el process id y en los procesos hijos -el proceso recién creado no tiene hijos y el proceso padre pasó a tener un hijo más-.

En cuanto al espacio de memoria del nuevo proceso, se utiliza la técnica de copy on write para lograr una mayor optimización. Empleando esta técnica ambos procesos tienen su espacio de memoria pero esta división comienza siendo “virtual”. A medida que se realizan operaciones de escritura en la memoria, se duplican las páginas que corresponden.

La etapa de exec permite la carga en memoria y ejecución de un binario. Veremos en este artículo solo forking.

A continuación la parte más divertida:

#include <stdio .h>
#include <stdlib .h>
#include <unistd .h>
 
int main(int argc, char* argv[]){
    pid_t id_del_proceso_hijo = fork();
    pid_t proceso_actual = getpid();
    printf("Mensaje de %d: Mi hijo es %d\n", proceso_actual, id_del_proceso_hijo);
    int* status_ptr = malloc(sizeof(int));
    *status_ptr = -1;
    pid_t estado_del_hijo = waitpid(id_del_proceso_hijo, status_ptr, 0x0);
    printf("Mensaje de %d: Espere hasta que se reportó el proceso %d. Info del reporte: %d\n", proceso_actual, estado_del_hijo, *status_ptr);
    return 0;
}
</unistd></stdlib></stdio>


Leer el resto del artículo »

3
Mar
2011

mtrace: debug de memoria en C (LibC)

La función mtrace proporcionada por LibC nos permite trazar todos las operaciones de obtención, redimensionamiento y liberación de memoria realizadas por las funciones malloc, realloc y free respectivamente. De esta forma, es posible detectar memory leaks (memoria sin liberar) en nuestra aplicación.

La función mtrace se vale de la variable de entorno MALLOC_TRACE para conocer la ruta donde guardar el resultado de las operaciones realizadas.

Con la función muntrace podemos detener el monitoreo iniciado por mtrace. Es posible encapsular bloques del programa con mtrace y muntrace.

Código de ejemplo:

#include <stdio .h>
#include <stdlib .h>
#include <mcheck .h>
 
int main () {
 
	setenv("MALLOC_TRACE", "/root/c/mtrace/output", 1);
 
	mtrace();
 
	void* puntero_a_memoria =  (void*)malloc(1);
 
	return 0;
}
</mcheck></stdlib></stdio>

Cambien el path /root/c/mtrace/out por el que les resulte conveniente. El proceso debe tener permisos de escritura allí.


Leer el resto del artículo »

3
Mar
2011

Variables de entorno con LibC

LibC provee algunas funciones para manejar las variables de entorno. Debemos incluir la Standard Library (stdlib.h) para acceder a ellas.

Limpiar las variables de entorno:

int clearenv(void);

Escribir o modificar una variable de entorno:

int putenv(char *string);

El parámetro string es de la forma VARIABLE=valor

Escribir o modificar una variable de entorno:

int setenv(const char *name, const char *value, int overwrite);

name es el nombre de la variable de entorno, value el valor y overwrite (0 o número distinto de 0) permite especificar la acción para el caso de que la variable de entorno ya exista con un valor determinado.

Remover una variable de entorno:

int unsetenv(const char *name);

name es el nombre de la variable de entorno.

3
Mar
2011

Variables de entorno en bash

Las variables de entorno de una shell Linux se utilizan para trabajar sobre ella o para dar información de contexto a los procesos que desde ella se ejecuten. Ese contexto sirve de datos al proceso y le permite, por ejemplo, modificar su compartamiento.

Las shells tienen un conjunto de variables de entorno cargadas por defecto. Los usuarios pueden definir más variables y modificar los valores existentes. Sin embargo, cualquier cambio realizado es temporal: al abrir una nueva shell, nos encontraremos nuevamente en el estado por defecto.

Los siguientes comandos aplican a la shell bash.

Para ver las variables de entorno:

printenv

Para imprimir el valor de una variable específica:

echo $VARIABLE

En caso de que la variable sea utilizada únicamente en la shell, podemos definirla de la siguiente forma:

VARIABLE=valor


Leer el resto del artículo »

2
Mar
2011

Disowning procesos en Linux

disown procesos linux

Cuando ejecutamos procesos en Linux desde un terminal, los procesos quedan “atados”. Esto significa que al cerrar el terminal, los procesos mueren. Voy a comentarles en este artículo dos formas de crear procesos independientes, que pertenecen al usuario desde el que se ejecutaron pero a ningún terminal en particular.

nohup

Lanzamos el proceso de la siguiente forma:

nohup ping 127.0.0.1

Con Ctrl + z detenemos el proceso para volver al terminal. Ingresando bg lo enviamos al background y podremos cerrar el terminal sin que el proceso muera.


Leer el resto del artículo »