domingo, 11 de enero de 2015

Restaurar libmmcamera_imx179.so Nexus 5

He modificado la librería de la cámara en mi Nexus 5 para poder grabar a 60 fps usando L Camera. Lastimosamente la experiencia no fue muy buena y necesitaba volver a mi cámara original.

Si deseas restaurar la biblioteca libmmcamera_imx179.so y no te funciona el método oficial, entonces puedes descargar esta app llamada LIB CHANGER:

Descarga desde la pag oficial <--- Recomendado
Descarga desde mediafire

Basta con copiar los ficheros a la sdcard y ejecutar con algún gestor de ficheros. Luego se presiona sobre el botón "RESTORE TO NORMAL" y listo, ahora puedes usar tu cámara común y corriente.



viernes, 2 de enero de 2015

domingo, 28 de diciembre de 2014

Guardar matriz en Memoria Compartida

Ya sabemos que no se pueden almacenar punteros en memoria compartida (las direcciones de memoria son diferentes para diferentes procesos). Esto acarrea que no se puedan crear vectores multidimensionales de la manera "tradicional" ( int ** ). 
La solución esta en emular las matrices al puro estilo de malloc (método index magic). 

Supongamos que queremos declarar una matriz de enteros de 5x5 en memoria compartida.

El tamaño de la memoria será: el tamaño del tipo de dato multiplicado por la cantidad de columnas y la cantidad de filas.

int id_Memoria = shmget (key,sizeof(int) * 5 * 5, 0777 | IPC_CREAT);



Ahora para acceder a la memoria sería:

// nCol = Cantidad de columnas de la matriz
matriz[x][y] ----> matriz[y * nCol + x];



Ejemplo con código:



  1. int nFil = 5; // numero de filas
  2. int nCol = 5; // numero de columnas
  3. int row, column;
  4. int *matrix;
  5.  
  6. // Crea el segmento de memoria compartida
  7. id_shmem = shmget(ipc_key, sizeof(int)*nFil*nCol, IPC_CREAT|0777); 

  8. matrix = (int *)shmat(id_shmem, 0, 0);
  9.  
  10. matrix[3*nCol + 2] = 1; // Equivalente a matrix[2][3]   


Links: 

http://stackoverflow.com/questions/1961504/is-it-possible-to-allocate-a-2d-array-as-shared-memory-with-ipc

jueves, 25 de diciembre de 2014

Conectar señales de Qt con funciones en C

La nueva sintaxis de Qt 5 nos permite conectar señales de objetos de Qt con funciones estáticas comunes.

Para ello usamos la siguiente sintaxis:

connect(emisor,  &ClaseDelEmisor::señal,  funcion);

Por ejemplo:


connect(timer, &QTimer::timeout, &f );



Ejemplo:

/** Cuando se vence el tiempo del timer y se envia
     la señal timeout() se ejecuta la función f **/


void f(){
    qDebug()<<"&timer.timeout ----> f()";
}


int main(int argc, char *argv[])
{   
    QCoreApplication a(argc, argv);    
    QTimer *timer = new QTimer();


    // Se conecta la señal timeout con la función f
    timer->connect(timer, &QTimer::timeout, &f );    

    timer->start(1000);    
    return a.exec();
}

Diagrama:



Links:

viernes, 19 de diciembre de 2014

Manejo de grupos de procesos: setpgid y getpgid

Los grupos de procesos se usan para controlar a un conjunto de procesos asociados entre si a través de un identificador. De manera especifica se emplean para la distribución de señales. Así, si se le envía una señal al grupo de procesos cada uno de los miembros de ese grupo recibe dicha señal. El identificador del grupo de proceso recibe el nombre de pgid. 

Es importante saber que:
  • Todo proceso pertenece a un grupo de procesos.
  • En un grupo de procesos pueden haber uno o más procesos.
  • Cuando un proceso crea un hijo este hereda el PGID del padre.
  • Un proceso puede cambiarse de grupo usando la función setpgid()
  • Cualquier proceso puede saber a que grupo pertenece otro proceso si conoce el PID.


Asignar un PGID


int setpgid(pid_t pid, pid_t pgid);

La función setpgid asigna un pgid al proceso a un proceso. El parámetro 
pid indica el PID del proceso a modificar. Si pid es cero, se emplea el PID del proceso en curso. 
Si pgid es cero, se emplea el PID del proceso especificado por pid. 
Si setpgid se utiliza para mover un proceso de un grupo de procesos a otro (como hacen algunos shells cuando crean tuberías), ambos grupos de procesos deben formar parte de la misma sesión. En este caso, pgid especifica el grupo de procesos existente en el que vamos a entrar, y el ID de sesión de ese grupo de procesos debe coincidir con el ID de sesión del proceso que quiere entrar. En  caso de éxito, setpgid y setpgrp devuelven cero. En caso de error. devuelven -1  y ponen un valor apropiado en errno

Obtener un PGID


La función getpgid devuelve el ID del grupo de proceso del especificado por pid. Si pid es cero, se emplea el PID del proceso en curso. getpgid devuelve un grupo de proceso si acaba bien; -1 en caso de error, y pone  un  valor apropiado en errno.

Enviar señales a un grupo de procesos

Se usa la función kill, con la salvedad que el pgid debe ser negativo. Esto para diferenciar del PID de algun proceso.
kill(-PGID, SIGNAL) // Note el signo negativo antes del PGID


Ejemplo #1:

En este ejemplo el proceso principal ( P1 ) creará 5 procesos hijos, los cuales heredarán su PID. 
Los hijos se dormirán al crearse y esperarán la señal del padre. 
El padre luego de crearlos duerme 2 segundos y luego le envía un mensaje a su propio grupo de procesos para despertar a todos los hijos.
Para ello usa kill(-getpgid(getpid()),SIGCONT);



#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <signal.h>

using namespace std;

// SIGCONT Signal handler
void h(int){}

int main(int argc, char *argv[])
{
    signal(SIGCONT,&h);
    int pid=0;
    cout<<"PID Padre="<<getpgid(getpid())<<endl;
    cout<<"PGID Padre="<<getpgid(getpid())<<endl;

    // El padre crea 5 hijos
    for (int i = 0; i < 5; ++i) {
        pid=fork();

        // Hijo
        if (pid==0){
            cout<<"Hijo "<<getpid()<<": Mi PGID es="<<getpgid(getpid())<<endl;

            // EL hijo se duerme
            sleep(300);

            // Cuando recibe la señal SIGCONT el hijo se despierta
            cout<<"Hijo "<<getpid()<<": Me despertaron"<<endl;
            exit(0);
        }
    }

   sleep(2);
   cout<<"Padre: envío SIGCONT al grupo "<<getpgid(getpid())<<endl;

   // Note que para enviar al grupo de procesos el valor
   // debe ser negativo
   kill(-getpgid(getpid()),SIGCONT);
}



Links de interés:


jueves, 18 de diciembre de 2014

Ejemplo de manejo de MEMORIA COMPARTIDA en Linux

Para manejar memoria compartida basta con realizar estos tres pasos:


Lo primero es crear la clave para la memoria compartida. Para ello se usa la función ftok que recibe dos parámetros: La ruta de un fichero existente y un número para generar la clave:

// Se crea la clave para la memoria compartida
clave = ftok ("/bin/ls", 34);

Luego creamos la memoria con la clave conseguida. Para ello usamos shmget. 
El primer parámetro es la clave
El segundo es la cantidad de bytes que se va a ocupar la memoria. En este caso queremos reservar espacio para un solo entero.
El tercero son los flags (permisos y modos). IPC_CREAT indica que debe crear la zona de memoria si esta no existe. En caso de que exista la usa de igual forma. Si se le agrega IPC_EXCL falla si el id ya existe. Esto para evitar usar una zona que ya este en uso o creada.

// Se crea la memoria compartida
id_Memoria = shmget (clave,  sizeof(int)*1,  0777 | IPC_CREAT);

Por último obtenemos la dirección de la memoria compartida y la guardamos en un puntero. para ello usamos shmat. El primer parametro es el id que obtuvimos con shmget. El resto de parámetros basta con colocarlos en cero :) 
// Se apunta a la dirección de memoria compartida 
memoriaCompartida = (int *)shmat (id_Memoria, (char *)0, 0);
Con estos tres pasos ya podemos usar la memoria compartida.
En este ejemplo vemos a dos procesos:

* Restador: Decrementa el valor de la memoria compartida.
* Sumador:  Incrementa el valor de la memoria compartida.
En la memoria compartida estará alojado un entero


Este es el código del sumador. El del restador es casi igual, solo que en vez de incrementar decrementa.
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <stdlib.h>

using namespace std;

int main()
{
    key_t clave=0;
    int id_Memoria=0;    
    
    int *memoriaCompartida = NULL;

    // Se crea la clave para la memoria compartida
    clave = ftok ("/bin/ls", 34);   
    if (clave == -1){
        cout << "No consigo clave para memoria compartida" << endl;
        exit(0);
    }

    // Creamos la memoria con la clave recién conseguida. Para ello llamamos
    // a la función shmget pasándole la clave, el tamaño de memoria que
    // queremos reservar (100 enteros en nuestro caso) y unos flags.
    // Los flags son  los permisos de lectura/escritura/ejecucion
    // para propietario, grupo y otros (es el 777 en octal) y el
    // flag IPC_CREAT para indicar que cree la memoria.
    // La función nos devuelve un identificador para la memoria recién
    // creada.
    //
    id_Memoria = shmget (clave, sizeof(int)*1, 0777 | IPC_CREAT);
    if (id_Memoria == -1)    {
        cout << "No consigo Id para memoria compartida" << endl;
        exit (0);
    }

    //
    // Una vez creada la memoria, hacemos que uno de nuestros punteros
    // apunte a la zona de memoria recién creada. Para ello llamamos a
    // shmat, pasándole el identificador obtenido anteriormente y un
    // par de parámetros extraños, que con ceros vale.
    //
    memoriaCompartida = (int *)shmat (id_Memoria, (char *)0, 0);
    if (memoriaCompartida == NULL)
    {
        cout << "No consigo memoria compartida" << endl;
        exit (0);
    }

    // Ya podemos utilizar la memoria.
    // Escribimos cosas en la memoria. Los números de 1 a 10 esperando
    // un segundo entre ellos. Estos datos serán los que lea el otro
    // proceso.
    //
    while (true)
    {
        // Incrementa el valor en memoria compartida
        memoriaCompartida[0]++;
        cout<<"Valor del entero en Memoria compartida = "<<memoriaCompartida[0]<<endl;
        fflush(stdout);
        sleep(1);
    }

    // shmdt desasocia una region de memoria compartida del espacio
    //  de direcciones virtuales del proceso
    //
    shmdt ((char *)memoriaCompartida);

    // Marca el ID de la memoria para ser destruido:
    // NO DESTRUYE la memoria, solo la marca.
    // Cuando se muere el ultimo proceso asociado a esa
    // memoria entonces el sistema se encarga de borrar la
    // memoria
    shmctl (id_Memoria, IPC_RMID, (struct shmid_ds *)NULL);
}
Puedes descargar el ejemplo DESDE AQUI.




¿Como funciona la función ftok?

La función ftok crea identificadores "únicos" para ser usados por funciones IPC (semget, shmget, msgget). 

Recibe dos parámetros:
* Una ruta a un fichero existente y accesible
* Un número

ftok ( char *pathname, char proj );

Ejemplo: ftok ( "/bin/ls", 34 );


La función busca el inodo del fichero indicado y lo combina con el número del segundo parámetro.

Note que si se pasa el mismo fichero y el mismo número a dos procesos que estén corriendo en la misma máquina entonces e generará la misma clave. Esto puede ser indeseado en muchos casos. Para evitar colisiones de clave es habitual usar el directorio actual de trabajo (.) como primer parámetro. El directorio actual es representado por un punto.

ftok ( ".", 89 );