Posted tagged ‘C’

Android como plataforma de desarrollo

25 abril, 2019

Hola a todos,

Trayéndoles las siguientes notas del curso de Android, ahora vamos a conocer a Android como plataforma de desarrollo. Conoceremos las herramientas con las que podemos producir aplicaciones Android, cómo se administra la ejecución de las aplicaciones, cómo y qué se debe tomar en cuenta al desarrollar una aplicación.

Aquí las notas: http://www.nachintoch.mx/teaching/mobile_dev/android-framework.pdf

Cómputo concurrente: herramientas de sincronización y concurrencia estándares en Python, C y C++

6 marzo, 2017

Hola a todos!

Una vez más, esta es una publicación que tiene ya rato en la sala de espera (unos 6 meses :S ); pero como mala hierba nunca muere, estoy de vuelta para compartir más notas de clase 😛

En esta ocasión, les paso un par de notas:

Como siempre, espero que les sea de utilidad y que el límite sea la imaginación.

Cómputo concurrente: Ejemplos de solución al problema del consenso en Java y C (Uso de las herramientas de concurrencia)

28 noviembre, 2015

Hola a todos!

Cerrando con broche de oro las clases de ayudatía que di este semestre, veremos a continuación algunos ejemplos para resolver problemas de concurrencia y en general de cómputo paralelo.

Les presento a continuación las notas, donde les explico las herramientas. Los ejemplos en C, pueden usarse en proyectos C++, y con algunas modificaciones, también puede usarse con varios sistemas basados en UNIX (incluyendo Mac OS X) y con la WinApi para su uso con Windows.

En el programa en C, se ilustra también cómo capturar una señal, por ejemplo la que se dispara cuando el usuario da la orden de interrumpir el comando actual usando ctrl +C (SIGINT).

En las notas encontrará más información al respecto:
http://nachintoch.mx/teaching/texts/23_nov%20-%20Ejemplos%20en%20Java%20y%20C%20soluci%C3%B3n%20al%20problema%20del%20consenso.pdf

El código de los ejemplos, puede encontrarlo en el siguiente repositorio en GitHub:
https://github.com/Nachintoch/ejemplos-concurrencia


 

Antes de terminar, quiero comentar algunos detalles sobre los ejemplos.

Primero que nada, la sección del makefile para compilar la implementación en C carece de las banderas para GCC mencionadas en las notas -ffixed-reg. Esto es porque (y lo aprendí a la mala), es mala idea usar registros cómo “variables globales compartidas” de un programa en C.

¿Porqué?

Al declarar la variable compartida, lo que tenemos es básicamente acceso a algún registro que nosotros hayamos elegido. Luego, como es compartida, usamos mmap para solicitar dicho espacio de memoria compartida y alojamos el apuntador que refiere al valor almacenado en el registro seleccionado. Esto suena a trabalenguas y es el punto clave, así que lo explicaré con calma.

register int *var asm(“%eax”);

Lo anterior declara una variable de C llamada “var”. Es de tipo apuntador a un entero de registro del procesador. Y además, solicitamos un registro estático para toda la vida del programa: el registro de procesador eax (en sintaxis para ensamblador de x86, x86_64 y amd64).

Entonces, tenemos un apuntador a un entero de registro. Queremos que este se convierta en una memoria compartida entre el proceso padre que ha hecho esta declaración y sus hijos que instancie de alguna manera más adelante en el flujo del programa.

Sería entonces lo esperado hacer algo como lo siguiente:

var = mmap(NULL, sizeof(*var), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);

mmap básicamente está solicitando al SO que nos de un espacio de memoria compartida y nos devuelve la dirección de memoria en la que el SO nos dió dicho espacio de memoria (o NULL (0) si el sistema no tiene suficiente memoria o por alguna otra razón rechaza la petición).

Cómo var es un apuntador, felizmente almacenamos la dirección de memoria retornada por mmap en var directamente y así tenemos un registro cuya dirección de memoria es compartida entre todos los procesos hijos y este padre. Genial ¿no?

Pues no mucho… ¿Qué pasa si el sistema interrumpe al proceso padre y lo envía a memoria? Uno esperaría que nada y que los hijos puedan seguir manipulando a donde apunta var felizmente, ya que es un espacio de memoria compartida ¿cierto?

Pero, var apunta a un registro de procesador, que además está en el contexto de ejecución del proceso padre que por el momento no está en ejecución, por lo que su contexto no está en el procesador, si no en memoria… Empieza a sonar feo ¿no?

Con el proceso padre sin tiempo de procesador, si un hijo intenta acceder a donde apunta var, accederá a una dirección del memoria -por el momento inválida- y normalmente el SO terminará matando al proceso hijo que hizo dicho intento.

Bajo nuestra aplicación anterior, esto es muy malo, ya que si justo ese era el proceso que debía hacer la llamada sem_post para permitir el progreso del otro proceso distinguido, esta condición habrá causado un deadlock.


 

Entonces, ¿usar variables registros o no usar variables registros? Esa es la cuestión.

La respuesta es la misma que si preguntamos cuando conviene usar un unsigned short int o un long long int: cuándo sea necesario y conveniente. La conveniencia de usar una variable registro, dependerá del problema a resolver y será necesario, en principio cuándo necesitemos usar una variable atómica por un muy breve periodo de tiempo y que además no necesitará ser una variable compartida.


 

Tomando en cuenta estas observaciones, podemos usar lo aprendido en estos ejemplo y algunas notas anteriores, para desarrollar aplicaciones concurrentes en distintas plataformas y al menos usando Java y C.

¡espero les sea de utilidad!

Saludos a todos!


A %d blogueros les gusta esto: