miércoles, 19 de marzo de 2014

Error en VMware al compilar el kernel "Failed to build vmnet"

Es común actualizar los programas dentro de nuestro GNU/Linux, así evitamos tropezar con algunos errores o bugs, mejoramos la estabilidad de nuestro sistema e incluso disfrutamos novedades de las nuevas versiones.

Al actualizar los paquetes de Fedora 19, tuve un pequeño inconveniente con VMware Workstation. El kernel había pasado de la versión 3.12 a la versión 3.13 y en esta versión existe un problema al compilar el módulo vmnet de VMware. Este problema también se presenta en Fedora 20 y es muy probablemente en todas las distribuciones GNU/Linux con kernel 3.13, tal es el caso de Arch Linux.

Problema


Tras terminar de instalar VMware Workstation o al actualizar Fedora podemos tropezar con los siguientes mensajes en secuencia:
Before you can run VMware, several modules must be compiled and loaded into the running kernel
"Before you can run VMware, several modules must be compiled and loaded into the running kernel"
Stopping VMware Services. Virtual Network Device, Running depmod. Starting VMware Services
Unable to start services. See log file /tmp/vmware-root/vmware-modconfig-wxyz.log for details
"Unable to start services. See log file /tmp/vmware-root/vmware-modconfig-wxyz.log for details"

Al visualizar el archivo mencionado en el mensaje observaremos al final:

# cat /tmp/vmware-root/vmware-modconfig-wxyz.log

Extracting the vmnet source from "/usr/lib/vmware/modules/source/vmnet.tar".
Successfully extracted the vmnet source.
Building module with command "/usr/bin/make -j8 -C /tmp/modconfig-xPv9iG/vmnet-only auto-build HEADER_DIR=/lib/modules/3.13.5-103.fc19.x86_64/build/include CC=/usr/bin/gcc IS_GCC_3=no"
Failed to build vmnet.  Failed to execute the build command.

¡ Qué problema !

Solución simple


Para saltar el problema en nuestro VMWare Workstation 10, simplemente reiniciamos nuestro sistema operativo. Antes de iniciar Fedora tendremos en pantalla al gestor de arranque Grub. En él seleccionamos Fedora con el kernel 3.12 (con las teclas de arriba y abajo) e iniciamos Fedora presionando ENTER. Con eso el problema habrá desaparecido.

Solución definitiva


Bien, si queremos dar una solución completa al problema que tenemos con nuestro kernel y el módulo vmnet de VMware sigamos los siguientes pasos:

Descarguemos el parche

$ curl http://pastie.org/pastes/8672356/download -o /tmp/vmware-netfilter.patch

Ingresemos al directorio donde está el código fuente de VMware Workstation

$ cd /usr/lib/vmware/modules/source

Ahora ingresemos como superusuario

$ su
[Password de root]

Descomprimamos el paquete vmnet.tar

# tar -xvf vmnet.tar

Ahora apliquemos el parche

# patch -p0 -i /tmp/vmware-netfilter.patch

Volvamos a empaquetar el directorio vmnet-only

# tar -cf vmnet.tar vmnet-only

Eliminemos los rastros del parche

# rm -r vmnet-only

Y finalmente volvamos a configuar vmware

# vmware-modconfig --console --install-all

Con esos pasos ya podemos utilizar nuevamente y sin ningún problema nuestro virtualizador de sistemas Operativos VMware Workstation.

Fuente de referencia: fedoraproject.org/wiki/VMWare


Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



lunes, 10 de marzo de 2014

Instalar ApiGen en Linux e Integrar con NetBeans

ApiGen es la herramienta para la creación de documentación profesional de API desde el código fuente PHP, similar al discontinuado phpDocumentor/phpDoc.

ApiGen tiene soporte para PHP 5.3 espacios de nombres, paquetes, vinculando entre la documentación, referencias cruzadas a PHP clases estándar y la documentación general, la creación de código fuente resaltada y soporte experimental para PHP 5.4.

ApiGen utiliza un sistema de plantillas Nette Framework y Texy para producir documentación HTML útil y fácil de leer, FSHL ​​de crear código fuente resaltada y TokenReflection para describir el código fuente documentado.

Instalar ApiGen

La forma mas facil de instalar ApiGen en su distribución Linux ya sea Ubuntu, Mint, Fedora, Red Hat, OpenSuse entre otros, es utilizando el paquete de PEAR, a continuación describo las maneras de cómo instalar ApiGen.

Instalar a traves de PEAR

PEAR es un sistema de distribución de paquetes PHP. Se incluye con PHP desde la versión 4.3 y es fácil de usar. Para utilizarlo primero verifique si PEAR esta instalado en su sistema, ejecute el comando:

# pear

Si obtiene un mensaje similar a "bash: pear: no se encontró la orden" Instalelo con la siguiente orden (todo como superusuario):

# yum install php-pear

El paquete PEAR contiene en sí ApiGen. Sus dependencias (Nette, Texy, FSHL ​​y TokenReflection) tienen que ser instalados por separado. Pero no se preocupe, el instalador de PEAR se hará cargo de ellas.

La forma más sencilla de instalarlo es utilizando la función de detección automática de PEAR. En ese caso, todo lo que tiene que hacer es escribir dos comandos:

# pear config-set auto_discover 1
# pear install pear.apigen.org/apigen

Ahora bien, si no desea utilizar la detección automática, usted tiene que añadir canales PEAR de todas las bibliotecas ApiGen manualmente. En este caso puede instalar ApiGen escribiendo estos comandos:

# pear channel-discover pear.apigen.org
# pear channel-discover pear.nette.org
# pear channel-discover pear.texy.info
# pear channel-discover pear.kukulich.cz
# pear channel-discover pear.andrewsville.cz

# pear install apigen/ApiGen

Si se encuentra con un mensaje como : WARNING: channel "pear.apigen.org" has updated its protocols, use "pear channel-update pear.apigen.org" to update, tiene que ejecutar el siguiente comando en su consola:

# pear channel-update pear.apigen.org

Una vez instalado ApiGen tranquilamente podrá generar documentación PHP de manera automática ejecutando el comando:

$ apigen --source <Ruta al código fuente> --destination <Ruta destino de la documentación>

En este punto podriamos tropesar con un inconveniente ya conocido:

PHP Warning:  require(Texy.php): failed to open stream: No such file or directory in /usr/bin/apigen on line 48

Warning: require(Texy.php): failed to open stream: No such file or directory in /usr/bin/apigen on line 48
PHP Fatal error:  require(): Failed opening required 'Texy.php' (include_path='.:/usr/share/pear:/usr/share/php') in /usr/bin/apigen on line 48

Fatal error: require(): Failed opening required 'Texy.php' (include_path='.:/usr/share/pear:/usr/share/php') in /usr/bin/apigen on line 48

Corrigiendo error en ApiGen (Texy.php)

Abra su consola y edite el archivo apigen dentro de /usr/bin

# vi /usr/bin/apigen

Busque la linea:

@include '/usr/share/pear/Texy/texy.php';

y cambiela por:

@include '/usr/share/pear/texy/src/texy.php';

Guardemos los cambios y salgamos del editor (Presionemos 'ESC' luego 'wq' y 'ENTER') y con ello ya no tendremos ese problema.

Integrar ApiGen y NetBeans

Abra nuestro IDE de desarrollo, NetBeans 7 en mi caso

Vaya a Herramientas > Opciones

Seleccione 'PHP' y luego la pestaña 'ApiGen'

Presione 'Search' y seleccione alguna de las opciones que aparece, en mi caso /usr/bin/apigen

Presionemos Aceptar y con ello tendremos integrado nuestro generador de documentación ApiGen con NetBeans IDE


Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



viernes, 14 de febrero de 2014

El Juego de la Vida de Conway (Conway's Life) en JAVA


Aquí les traigo parte de la teoría del juego de la vida y su respectivo código fuente de la aplicación programado en java, con interfaz gráfica, espero les sirva el documento.

Concepto y descripción de autómatas celulares

John Von Neumann investigó la cuestión del origen de la vida y trató de diseñar una máquina capaz de reproducirse. La idea en el diseño de auto-reproducción llevó a Von Neumann a inventar un sistema denominado: Autómatas Celulares, capaces de construir cualquier autómata a partir de un conjunto apropiado de instrucciones codificadas.
Los Autómata Celulares se consideran sistemas dinámicos extendidos, que consisten de un número considerable de componentes simples idénticos con conectividad local, y son definidos como un sistemas que evoluciona en tiempo y espacio discretos, compuesto de una colección de celdas discretas y deterministas, ordenadas en fila, en forma de matriz o en tres dimensiones, que actualizan sus estados a lo largo del tiempo en base a los estados que tenían las celdas vecinas en el momento inmediato anterior, en otras palabras, el estado siguiente de una celda es determinado por el estado actual de ella y de sus celdas vecinas, donde cada celda se comporta como un autómata de estado finito. Un autómata finito es un modelo de sistema con entradas y salidas discretas, consiste en un conjunto finito de estados y un conjunto de transiciones entre esos estados. La entrada y el estado actuales del autómata determinan su conducta en el instante siguiente.

Un Autómata celular consiste de dos componentes: el primero es un espacio celular, una red de n celdas de estado finito, cada una con un patrón idéntico de conexiones locales con otras celdas, junto con condiciones de límite, si se trata de una red finita. El segundo componente consiste en reglas de transición que actualizan, o bien definen los estados de cada celda, donde éstos estados junto con el de las celdas conectadas a ellas dan lugar a lo que es una vecindad.


El Juego de La Vida de Conway (Conway’s Life)

John Horton Conway nació en 1937, comenzó su carrera de Matemáticas en la Universidad de Cambrige. A finales de 1960 Conway, motivado por el trabajo de Von Neumann, siguiendo la idea de construir una máquina capaz de construir copias de sí misma y haciendo uso del concepto de vecindad de un autómata definido por Moore, diseñó y dió a conocer el autómata celular más famoso: El juego de la Vida (The Game of the Life), también llamado El Juego de Conway (Conway’s Life), un juego de sentido solitario, es decir, para un solo jugador. Éste juego es un autómata bidimensional donde cada célula puede estar en uno de los dos estados 0 o 1, (muerto o vivo). A partir de un estado inicial el autómata va a evolucionar en base a unas funciones de trancisión, además una célula estará en un estado concreto determinado unicamente por el estado anterior de las celulas vecinas, así como el de la propia célula.


Conway definió el siguiente conjunto de reglas:
  • SOLEDAD, si una célula viva esta sola o tiene un solo vecino muere.
  • SOBREPOBLACIÓN, si una célula viva tiene más de tres vecinos muere.
  • ESTABILIDAD, de lo contrario la célula se queda igual.

DISEÑO FORMAL DE AUTOMATA CELULAR DEL JUEGO DE LA VIDA

Conjunto de Estados
Q
(Muerto o Vivo)
Alfabeto
(0, 1)
Transición
Ҏ
Muerto (0) o Vivo (1)
Estado Inicial
qo
Estático
Conjunto de estados finales
F
Dinámico
Espacio de celulas
n x m
Número de Filas (n)
Número de Columnas (m)
Reglas de transición

  • Soledad
  • Sobrepoblación
  • Estabilidad

  • Si una célula viva esta sola o tiene un solo vecino muere.
  • Si una célula viva tiene más de tres vecinos muere
  • De lo contrario la célula se queda igual.


CODIFICACIÓN DE LOS ESTADOS:

public void procesar() {
        for (int i = 1; i < fil - 1; i++) {
            for (int j = 1; j < col - 1; j++) {
                int sum = m[i - 1][j - 1] + m[i][j - 1] + m[i + 1][j - 1] + m[i + 1][j] + m[i + 1][j + 1] + m[i][j + 1] + m[i - 1][j + 1] + m[i - 1][j];
                if (sum == 3) {
                    mt[i][j] = 1;
                } else if (sum != 2) {
                    mt[i][j] = 0;
                }
            }
        }
        this.copiaMatriz();
    }


CODIFICACIÓN DE ENTORNO Y DE EL PROGRAMA EN GENERAL:

Main.java:

/**
 * @author Andrea Dorado
 */

public class Main {
    public static void main(String[] args) {
        Ventana mjf = new Ventana();
        mjf.setSize(900, 650);
        mjf.setVisible(true);
    }
}


Ventana.java:

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

/**
 * @author Andrea Dorado
 */
public class Ventana extends JFrame implements ActionListener {

    JMenuBar menuBar;
    JMenu mnFile;
    JMenuItem mniExit;
    Lienzo pnlGraphic;
    JPanel pnlEast, pnlEastTop, pnlEastBottom;
    JToolBar toolBar;
    JButton btnEjecutar;
    ButtonGroup btnGroup;
    Timer timer;

    public Ventana() {
        super("INF - 154 Lenguajes Formales y Autómatas (El Juego de la Vida)");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        menuBar = new JMenuBar();
        mnFile = new JMenu("Archivo");
        mniExit = new JMenuItem("Salir");
        pnlEast = new JPanel();
        pnlEastTop = new JPanel();
        pnlEastBottom = new JPanel();
        pnlGraphic = new Lienzo();
        toolBar = new JToolBar();
        btnEjecutar = new JButton("Ejecutar");
        btnGroup = new ButtonGroup();
        pnlEast.setLayout(new BoxLayout(pnlEast, BoxLayout.Y_AXIS));
        pnlEastTop.setLayout(new BoxLayout(pnlEastTop, BoxLayout.Y_AXIS));
        pnlEastBottom.setLayout(new BoxLayout(pnlEastBottom, BoxLayout.Y_AXIS));
        pnlEastBottom.setAlignmentX(Component.CENTER_ALIGNMENT);
        pnlEastTop.setAlignmentX(Component.CENTER_ALIGNMENT);
        menuBar.add(mnFile);
        mnFile.add(mniExit);
        pnlEast.add(pnlEastTop);
        pnlEast.add(pnlEastBottom);
        toolBar.add(btnEjecutar);
        toolBar.add(Box.createRigidArea(new Dimension(20, 0)));
        setJMenuBar(menuBar);
        this.add("North", toolBar);
        this.add("East", pnlEast);
        this.add("Center", pnlGraphic);
        mniExit.addActionListener(this);
        btnEjecutar.addActionListener(this);
        timer = new Timer(1000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                pnlGraphic.repaint();
            }
        });
       
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == mniExit) {
            System.exit(0);
        }
        if (e.getSource() == btnEjecutar) {
            timer.start();
        }
    }
}


Lienzo.java:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

/**
 * @author Andcrea Dorado
 */
public class Lienzo extends JPanel {

    int fil, col;
    int[][] m = new int[100][100];
    int[][] mt = new int[100][100];

    public Lienzo() {
        fil = 35;
        col = 50;
        m[3][2] = m[3][3] = m[3][4] = m[3][5] = m[3][6] = m[3][7] = m[3][8] = m[3][9] = m[3][11] = m[3][12] = m[3][17] = m[3][18] = m[3][20] = m[3][21] = m[3][22] = m[3][23] = m[3][24] = m[3][25] = m[3][26] = m[3][27] = m[3][35] = m[3][37] = m[3][38] = m[3][39] = m[3][40] = m[3][45] = 1;
        m[4][2] = m[4][3] = m[4][4] = m[4][5] = m[4][6] = m[4][7] = m[4][8] = m[4][9] = m[4][11] = m[4][12] = m[4][17] = m[4][18] = m[4][20] = m[4][21] = m[4][22] = m[4][23] = m[4][24] = m[4][25] = m[4][26] = m[4][27] = m[4][34] = m[4][35] = m[4][37] = m[4][40] = m[4][44] = m[4][45] = 1;
        m[5][5] = m[5][6] = m[5][11]=  m[5][12]=  m[5][13]= m[5][17]=m[5][18]=m[5][20]=m[5][21]=m[5][33]=m[5][35]=m[5][37]=m[5][43]=m[5][45]=1;
        m[6][5]=m[6][6]=m[6][11]=m[6][12]=m[6][13]=m[6][14]=m[6][17]=m[6][18]=m[6][20]=m[6][21]=m[6][22]=m[6][23]=m[6][32]=m[6][35]=m[6][37]=m[6][38]=m[6][39]=m[6][40]=m[6][42]=m[6][43]=m[6][44]=m[6][45]=1;
        m[7][5]=m[7][6]=m[7][11]=m[7][12]=m[7][14]=m[7][15]=m[7][17]=m[7][18]=m[7][20]=m[7][21]=m[7][22]=m[7][23]=m[7][27]=m[7][28]=m[7][29]=m[7][30]=m[7][35]=m[7][40]=m[7][45]=1;
        m[8][5]=m[8][6]=m[8][11]=m[8][12]=m[8][15]=m[8][16]=m[8][17]=m[8][18]=m[8][20]=m[8][21]=m[8][27]=m[8][28]=m[8][29]=m[8][30]=m[8][35]=m[8][40]=m[8][45]=1;
        m[9][2]=m[9][3]=m[9][4]=m[9][5]=m[9][6]=m[9][7]=m[9][8]=m[9][9]=m[9][11]=m[9][12]=m[9][16]=m[9][17]=m[9][18]=m[9][20]=m[9][21]=m[9][35]=m[9][37]=m[9][40]=m[9][45]=1;
        m[10][2]=m[10][3]=m[10][4]=m[10][5]=m[10][6]=m[10][7]=m[10][8]=m[10][9]=m[10][11]=m[10][12]=m[10][17]=m[10][18]=m[10][20]=m[10][21]=m[10][35]=m[10][37]=m[10][38]=m[10][39]=m[10][40]=m[10][45]=1;
        m[20][2]=m[20][3]=m[21][2]=m[21][3]=1;
        m[20][7]=m[21][7]=m[22][7]=m[19][8]=m[18][9]=m[18][10]=m[23][8]=m[24][9]=m[24][10]=1;
        m[21][11]=m[19][12]=m[20][13]=m[21][13]=m[22][13]=m[21][14]=m[23][12]=1;
       
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        int mi = 0;
        int mj = 0;

        Color colorActual = new Color(0, 0, 255);
        for (int j = 1; j < this.getHeight(); j += this.getHeight() / fil) {

            for (int i = 1; i < this.getWidth(); i += this.getWidth() / col) {
                if (m[mj][mi] == 1) {
                    g.setColor(colorActual);
                    g.fillRect(i, j, this.getWidth() / col, this.getHeight() / fil);
                }
                mi++;
            }
            mj++;
            mi = 0;
        }
        this.drawLine(g2d, Color.black);
        this.procesar();
    }

    public void drawLine(Graphics2D g2d, Color color) {
        g2d.setColor(color);
        for (int i = 0; i < getWidth(); i += this.getWidth() / 50) {
            g2d.drawLine(i, 0, i, getHeight());
        }
        for (int i = 0; i < getHeight(); i += this.getHeight() / 35) {
            g2d.drawLine(0, i, getWidth(), i);
        }
    }

    public void procesar() {
        for (int i = 1; i < fil - 1; i++) {
            for (int j = 1; j < col - 1; j++) {
                int sum = m[i - 1][j - 1] + m[i][j - 1] + m[i + 1][j - 1] + m[i + 1][j] + m[i + 1][j + 1] + m[i][j + 1] + m[i - 1][j + 1] + m[i - 1][j];
                if (sum == 3) {
                    mt[i][j] = 1;
                } else if (sum != 2) {
                    mt[i][j] = 0;
                }
            }
        }
        this.copiaMatriz();
    }

    public void copiaMatriz() {
        for (int i = 1; i < fil - 1; i++) {
            for (int j = 1; j < col - 1; j++) {
                m[i][j] = mt[i][j];
            }
        }
    }
}


Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



Administración de Procesos en Linux

GNU/Linux nos brinda un set de programas para realizar el monitoreo de los procesos en el sistema operativo que todo usuario con un poco de conocimiento sobre administración deberia conocer.

ps

El comando "ps" muestra información de los procesos activos en el sistema. Por defecto solo selecciona los procesos asociados a una terminal y a un usuario (quien ejecutó ps).
Algunos de los atributos que se muestran son:

  • PID - Identificador del proceso.
  • PPID - Identificador del proceso padre.
  • UID - Identificador del usuario propietario del proceso.
  • TTY - Terminal asociada al proceso, si no hay terminal aparece entonces un '?'.
  • TIME - Tiempo de uso de CPU acumulado por el proceso.
  • CMD - El nombre del programa asociado al proceso.
  • RSS - Espacio de memoria real del proceso [KB].
  • SIZE - Espacio de memoria virtual de la imagen del proceso.
  • NI - Nice, Prioridad del proceso.
  • %CPU - Porcentaje de CPU utilizado por el proceso.
  • STIME - Hora de inicio del proceso.
  • STAT - Estado del proceso (R Ejecutándose, S En espera, T Detenido, Z Zombie, X Muerto).

Para poder ver todos los procesos en el sistema use los siguientes parámetros:

Usando la sintaxis estándar:

  • -e. Selecciona todos los procesos, equivalente a usar -A
  • -f. Lista en formato completo.

$ ps -e
$ ps -ef

Usando la sintaxis BSD:

  • a. Muestra los procesos ejecutados a traves de una terminal. Si se utiliza el parámetro x listará todos los procesos.
  • u. Muestra el listado de manera mas apropiada para el usuario.

$ ps ax
$ ps aux

Consulte el manual en linea de ps para mas detalles.

$ man ps

Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



Programación de Procesos en GNU/Linux

Procesos

Un proceso en términos generales es un programa en ejecución, una instancia de programa que tiene asociado un conjunto de recursos como registros internos del procesador, un espacio
en memoria con segmentos de dato, código y pila.

Estado de un Proceso

Un proceso en el transcurso de su ejecución cambia de un estado a otro. Los diferentes estados posibles son:
  • Ejecución. El proceso es ejecutado por el procesador.
  • Listo. El proceso está en espera de ser seleccionado para ejecutarse.
  • Suspendido. El proceso está en espera de un recurso.
  • Parado. El proceso ha sido suspendido por una intervención externa.
  • Zombi. El proceso ha terminado su ejecución pero sigue siendo referenciado en el sistema.
El proceso se caracteriza por tener varios atributos mantenidos por el sistema:

  • Estado
  • Identificador, número único (PID)
  • Valor de los registros del procesador.
  • Identificador de usuario
  • Prioridad
  • Información de contabilidad
  • Otros.


Programar Procesos con Fork

Un proceso puede crear procesos hijo utilizando la llamada al sistema fork. El proceso actual se duplica y crea una copia idéntica con excepción de su identificador (PID). Fork retorna el PID del proceso hijo al padre y cero al proceso hijo. Es necesario conocer este valor de retorno para distinguir el código que ejecutará el proceso padre y el que ejecutará el proceso hijo. En caso de fallo, fork devuelve -1 por dos posibles razones:

  • Se ha llegado al número máximo de procesos de usuario o de sistema.
  • El kernel no ha podido asignar suficiente memoria para crear un nuevo proceso.


Para utilizar la llamada al sistema fork es necesario incluir la cabecera unistd.h

Ejemplo:

#include <errno.h>
#include <stdio.h>
#include <unistd.h>

void main() {

    pid_t pid;
    pid = fork();

    if(pid != -1) {
        if(pid == 0) {
            /*Instrucciones para el proceso Hijo*/
            printf("Hijo: pid = %d\n", pid);
        }
        else {
            /*Instrucciones para el proceso Padre*/
            printf("Padre: pidHijo = %d\n",pid);
        }
    }
    else {
        /*Error. no se creo el proceso hijo*/
        perror("fork");
    }
}

El proceso actual termina automáticamente cuando deja de ejecutar la función main. Si desea que el proceso termine su ejecución en algún momento, utilice la llamada la sistema exit.

void _exit (int estado);

El parámetro estado especifica el código de retorno, entre 0 y 255, que recibe el proceso padre. Se debe retornar 0 si finalizó de manera normal y otro valor si hubo algún error.

Espera de conclusión de procesos Hijo

El proceso padre puede esperar a que un proceso hijo finalice, mediante wait y waitpid.

La primitiva wait suspende la ejecución del proceso actual hasta que acabe algún proceso hijo. Si un proceso hijo ha terminado, wait devuelve el resultado inmediatamente.

pid_t wait (int *estadoProceso);

Ejemplo:

#include <stdio.h>
#include <unistd.h>

void main() {

    int estadoProceso;
    pid_t pid = fork();

    if(pid == 0) {
        printf("Proceso hijo, pid = %d\n", pid);
    }
    else {
        wait(&estadoProceso);
        printf("Proceso padre, pid hijo = %d\n", pid);
    }
}

La primitiva waitpid suspende la ejecución del proceso actual hasta que un proceso hijo específico termine.

pid_t waitpid (pid_t pid, int *estadoProceso, int opciones);

Ejemplo

#include <stdio.h>
#include <unistd.h>

void main() {

    pid_t pid1, pid2;
    int estadoProc1, estadoProc2;

    pid1 = fork();
    if (pid1 == 0) {
        printf("Proceso hijo 1 ejecutandose\n");
    }
    else {
        pid2 = fork();
        if(pid2 == 0) {
            printf("Proceso hijo 2 ejecutandose\n");
        }
        else {
            waitpid(pid1, &estadoProc1, 0);
            printf("Fin del proceso 1\n");
            waitpid(pid2, &estadoProc2, 0);
            printf("Fin del proceso 2\n");
            printf("Proceso padre: pidHijo1 = %d, pidHijo2 = %d\n", pid1, pid2);
        }
    }
}

Lectura y Modificación de atributos

El kernel Linux nos permite obtener y modificar los atributos de los procesos, entre estas llamadas al sistema están:

  • pid_t get pid() Retorna el identificador único del proceso actual
  • pid_t get ppid() Retorna el identificador único del proceso padre
  • uid_t get uid() Retorna el identificador del usuario que ejecutó el proceso
  • int setuid(uid_t uid) Modifica el identificador de usuario


Para que la llamada setuid() cambie efectivamente el identificador de usuario, el proceso debe ejecutarse
como superusuario.

Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



Llamadas al Sistema en Linux

Un proceso se ejecuta normalmente en modo usuario, cuando éste necesita algún recurso debe utilizar llamadas al sistema. En GNU/Linux, estas funciones tienen un nombre y número único de identificación. Este número puede encontrarse en la dirección /usr/include/asm/unistd.h.

Fragmento del archivo unistd_32.h:

#define __NR_restart_syscall      0
#define __NR_exit  1
#define __NR_fork  2
#define __NR_read  3
#define __NR_write  4
#define __NR_open  5
#define __NR_close  6
#define __NR_waitpid  7
#define __NR_creat  8
#define __NR_link  9
#define __NR_unlink 10

Cuando un proceso ejecuta una llamada al sistema, llama a la función correspondiente de la biblioteca C. Esta función trata los parámetros y pasa al núcleo.

El número de llamadas al sistema puede variar un poco en relación a la versión del kernel o a la distribución (Debian, red Hat, Slackware, etc), pero oscilan sobre las 300 llamadas.

Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



Utilizar Gcc (GNU C Compiler) en Linux

El GNU/Linux está desarrollado en C, un lenguaje de programación de Alto nivel, por esta razón es necesario disponer de un compilador apropiado para que nuestros programas puedan ser ejecutados bajo este sistema operativo.

El compilador gcc (GNU C Compiler) nos permite entre otras cosas generar archivos ejecutables, se caracteriza por ser potente, rápido, realiza optimización y tiene soporte para todos los estándares de programación en C.

Gcc permite encadenar las diferentes fases de compilación de un programa:

  • Preprocesador. En nuestro código se incluyen los archivos de cabecera utilizados. Programas cpp, gcc -M
  • Compilación. Se hace la compilación efectiva del código generando instrucciones en ensamblador y optimizándolo. Programas ccl, gcc -S
  • Ensamblado. El código se ensambla y genera un archivo objeto asociado. Programa gcc -c
  • Enlazado. Se genera el archivo ejecutable del programa, reuniendo todos los archivos objeto y enlazándolos. Programa ld

Si se quiere usar gcc para compilar algún programa, basta escribir en una terminal:

$ gcc nombrePrograma.c

Como resultado tendrá un ejecutable con el nombre a.out por defecto. Para especificar un nombre en particular utilice el parámetro -o:

$ gcc -o nombrePrograma.c nombreEjecutable

Para ejecutar el programa anteponga ./ al nombre del ejecutable:

$ ./a.out

o

$ ./nombreEjecutable

según corresponda.


Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.