Noticias Weblogs Foros Wiki Código
Sponsors:

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Sponsors

PlanetaCódigo en inglés

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin

Métricas Web

Consejos para el desarrollo en C en sistemas UNIX

Noviembre 30th, 2005 - [Enlace local]

Hace poco me tuve que enfrentar al desarrollo de un pequeño servidor de "servicios" en UNIX (un programa similar a un servidor web). Os pongo aquí algunas observaciones y consejos que tuve en cuenta en el momento del desarrollo, por si os pueden ayudar.

- Gestión del log de la aplicación:

Crear un buffer de línea para el log:

setvbuf(access_log, (char *) NULL, _IOLBF, 0); (acces_log es el descriptor del fichero de log que abrimos siempre con los flags de concatenación)

Con este buffer nos aseguramos que en cuanto se llene una línea esta se escriba inmediatamente al fichero.

Podemos redirigir la salida estándar de errores al log de error mediante dup2 (duplicación de descriptores de fichero)

dup2(error_log, STDERR_FILENO) Todo lo que valla al STDERR_FILENO (la salida de error) irá a nuestro log cuyo descriptor es error_log

También lo podemos hacer para la salida estandar mediante: STDOUT_FILENO

Otro truco, si no queremos que el programa imprima nada por las salidas estándar, es abrir el fichero /dev/null asignándole, por ejemplo, el descriptor dev_null y hacer lo siguiente:

dup2(dev_null, 1); dup2(dev_null, 2);

Para escribir en el log conviene utilizar fputs antes que fprintf ya que en sistemas SOLARIS si escribís algo NULL podéis tener problemas con fprintf.

También podemos poner el flag Close on exec a TRUE:
fcntl(acces_log, F_SETFD, 1)
... si vamos a utilizar cualquier función de la familia exec, de esta forma no se heredan los descriptores de fichero abiertos.


- Lanzar el programa como un demonio (si está destinado a ese fin).

Podemos utilizar fork() de la siguiente forma al inicio del proceso para que se nos ponga en background.

if (fork())
exit(0) // terminamos el proceso padre

setsid(); // El hijo ahora no tiene terminal asociado y es el nuevo lider del grupo de procesos

if (fork())
exit(0) // terminamos el proceso padre

Gracias a Jim por avisar en los comentarios que faltaba el segundo fork

- Cuestiones de seguridad.

Nada más iniciar el programa podemos crearle una jaula chroot mediante la función:

chroot(/directorio/aplicacion)

De esta forma el proceso tomará como directorio "/" el /directorio/aplicación y no podrá salir de dicho directorio para leer o modificar otros ficheros.

Podemos cambiar el uid del proceso a uno sin privilegios mediante setuid. Si hemos lanzado el proceso con privilegios de root, por ejemplo, y nos interesa poder volver a ser root cuando queramos podemos utilizar seteuid.

Por ejemplo:
seteuid(852)
abrir un fichero o hacer algo
seteuid(0) // volvemos a ser root

Si hacemos un seteuid antes de un fork, el proceso hijo tendrá el uid indicado por el seteuid.

Establecer la máscara de creación de ficheros: mediante la función umask definimos los permisos con los que se crearán los nuevos ficheros.


- Capturar las señales que lleguen al programa.

Mediante la biblioteca sigaction podemos capturar todas las señales (exceptor SIGKILL o SIGSTOP) y asignarles un controlador. Esto es útil para poder cerrar los descriptores de ficheros, indicar en los logs que se está reiniciando, abortando el programa o realizar cualquier acción.


- Fijar los límites de consumo del programa.

Mediante la llamada al sistema setrlimit(); podemos fijar límites de consumo al proceso. Por ejemplo, el número máximo de descriptores de fichero que puede abrir (útil si trabajamos con sockets), también podemos limitar el uso de cpu etc... Para más información, este link.


- Obtener los parámetros de entrada al programa.

Os recomiendo utilizar la función getopt. En bulma tenéis un excelente tutorial para ello.


- Autoconf y Automake.

Con estas herramientas podemos hacer que nuestra aplicación siga el proceso de instalación estándar de GNU. Además, nos chequean el sistema antes de la instalación para ver que no falta ninguna biblioteca además de crearnos los makefiles para compilarlo. Os recomiendo leer Autobook


Seguro que me dejo algún truquito más en el tintero, agradezco comentarios y críticas (positivas o negativas) y ,por supuesto, mención a cualquier error que haya cometido en el artículo.



» Leer más, comentarios, etc...