Solaris IPC: Semáforos

IPC, OpenSolaris, Solaris, Tuning Dejar un comentario

Los semáforos son un elemento lógico utilizado para la sincronización entre procesos, existen varias forma de implementar un semáforo, en los Solaris encontramos la implementación System V. En este artículo vamos a ver de una forma bastante rápida la forma de consultar los semáforos del sistema, así como comprobar si los valores utilizados en los parámetros del Kernel que afecta a los semáforos son correctos o no.


En Solaris existe un elemento llamado Sets de semáforos, el cual es en realidad un grupo de semáforos, no existen los semáforos independientes, es decir, cuando nuestra aplicación necesita un semáforo le solicita al Kernel un Set de semáforos, el cual tendrá un número determinado de ellos mediante la llamada a sistema semget(), que acepta como parámetros una key que define al set de semáforos, el número de los semáforos del set y los permisos que tendrá el set de semáforos.

Una de las cosas que han cambiado de Solaris 9 a Solaris 10 ha sido la forma en la que definimos en el sistema cuantos semáforos podemos crear. Debido a que todavía existen muchos Solaris 9 instalados, sobre todo en entornos de producción, vamos a comenzar viendo como se definen los semáforos en Solaris 9 y posteriormente veremos cómo lo podemos hacer en Solaris 10.

Semáforos en Solaris 9

Para ver cómo están configurados los semáforos en nuestro sistema Solaris 9, debemos ejecutar el comando sysdef, el cual nos devolverá una lista con varios parámetros del Kernel.

 

(root@huelva_9)# sysdef
*
* Hostid
*

*
* sun4us Configuration
*
*
* Devices
*
packages (driver not attached)
        terminal-emulator (driver not attached)
        deblocker (driver not attached)
        obp-tftp (driver not attached)
        disk-label (driver not attached)

...

*
* IPC Semaphores
*
   100  semaphore identifiers (SEMMNI)
  3000  semaphores in system (SEMMNS)
  4096  undo structures in system (SEMMNU)
   438  max semaphores per id (SEMMSL)
   100  max operations per semop call (SEMOPM)
    64  max undo entries per process (SEMUME)
 32767  semaphore maximum value (SEMVMX)
 16384  adjust on exit max value (SEMAEM)

...

(root@huelva_9)#

La salida de sysdef será parecida a la anterior, podemos ver en el ejemplo, que existen una serie de línea, las cuales tienen definidos unos valores, en la siguiente tabla vamos a realizar una correspondencia con los parámetros del Kernel y la salida de sysdef, así como una breve descripción.

Parm. Kernel Sysdef Descripción
semsys:seminfo_semmni SEMMNI Número de identificadores de semáforos que puede tener el sistema. Corresponde al número de sets.
semsys:seminfo_semmns SEMMNS Número máximo de semáforos en el sistema
semsys:seminfo_semmsl SEMMSL Número máximo de semáforos por ID

En nuestro ejemplo, el sistema tiene 100 Sets de semáforos y cada uno tiene 438 semáforos, esto significa que podríamos llegar a tener 100 x 438 semáforos en el sistema, normalmente, esta cantidad es excesiva y Solaris 9 dispone del parámetro SEMMNS para limitar el número de semáforos que se pueden utilizar.

Cuando estemos planificando el número de semáforos que vamos a necesitar en el sistema, tenemos que tener en cuenta:

  • Cuantos sets de semáforos vamos a necesitar.
  • Cuantos semáforos tendrá cada Set.
  • Que el producto de los Sets de semáforos activos y el número de semáforos activos de cada Set, sea inferior al valor del parámetro semsys:seminfo_semmns (SEMMNS).

Una vez que conocemos como están configurados los distintos parámetros que afectan a los semáforos en el Kernel, vamos ver qué herramientas tenemos disponibles en el sistema para consultar el estado de los semáforos. Una de estas herramientas es el comando ipcs y la otra herramienta, como no podía ser de otra forma, es el mdb (Modular Debugger).

El comando ipcs

Este comando nos devuelve información sobre el estado de los distintos IPCs activos en el sistema como son, Memoria compartida, Mensajes y Semáforos, ahora solo vamos a ver como ipcs nos puede ayudar con los semáforos, el resto de IPCs los veremos en otros artículo dedicados a cada uno de ellos.

El man dispone de una información detallada sobre todas las opciones del comando ipcs, por lo que no entraremos en la descripción de cada uno de ellos. Para ver el estado de los semáforos activos en el sistema, ejecutaremos:

 

(root@huelva_9)# ipcs -sA
IPC status from  as of Fri Jun 22 12:50:01 CEST 2007
T         ID      KEY        MODE        OWNER    GROUP  CREATOR   CGROUP NSEMS   OTIME    CTIME
Semaphores:
s          0   0x71b81609 --ra-ra-ra-     root     root     root     root     1 12:46:50 12:58:16
s      65537   0x53b81108 --ra-------     root     root     root     root     1 13:09:19 12:58:50
s          2   0xc3b      --ra-ra-ra-     root     root     root     root     3  9:19:03 12:59:55
s     393219   0xc3c      --ra-ra-ra-     root     root     root     root     3 21:10:33 12:59:58
s          4   0x31b82002 --ra-ra-ra-     root     root     root     root     1 12:50:00 12:59:59
s          5   0x310001f7 --ra-ra-ra-     root     root     root     root     1 12:50:00 12:59:59
s      65542   0xc9e03647 --ra-r--r--     root     root     root     root     3 13:00:18 13:00:18
s  165281799   0xa1866638 --ra-r-----  oracle9      dba  oracle9      dba   252 12:50:00  0:03:16
s   27590664   0xa1866639 --ra-r-----  oracle9      dba  oracle9      dba   252 no-entry  0:03:16
s    8781833   0xa186663a --ra-r-----  oracle9      dba  oracle9      dba   252  0:03:17  0:03:16
s   82575370   0x9ee686f8 --ra-r-----  oracle9      dba  oracle9      dba   352 12:49:58 19:13:56
s   12910603   0x9ee686f9 --ra-r-----  oracle9      dba  oracle9      dba   352 no-entry 19:13:56
s    3866636   0x9ee686fa --ra-r-----  oracle9      dba  oracle9      dba   352 19:13:57 19:13:56
s   31391757   0x6186af44 --ra-r-----  oracle9      dba  oracle9      dba   204 12:50:01  0:27:29
s    8126478   0xbd4cd75c --ra-r-----  oracle9      dba  oracle9      dba   227 12:49:09 12:01:40
s     983055   0xbd4cd75d --ra-r-----  oracle9      dba  oracle9      dba   227 no-entry 12:01:40
s    4128784   0xbd4cd75e --ra-r-----  oracle9      dba  oracle9      dba   227 12:01:40 12:01:40
s   27656209   0x55000a20 --ra-ra-ra-     root     root     root     root     1 18:02:06 11:05:52
(root@huelva_9)#

La salida del comando devuelve una lista con todos los sets de semáforos activos, la primera columna es el identificador de cada set, la columna KEY contiene una key que se ha utilizado al crear el set de semáforos, una columna con los permisos, el propietario del set, el grupo, el creador, el grupo del creador, el número de semáforos activos en cada set, el tiempo de la última operación sobre el set y el tiempo de la última modificación.

Lo que tenemos que tener en cuenta de la salida del comandos es:

  • Que el número de sets de semáforos que presenta el comando ipcs debe ser menor que el valor de semsys:seminfo_semmni (SEMMNI).
  • Que ningún set tenga en la columna NSEMS un valor cercano al parámetro semsys:seminfo_semmsl (SEMMSL), ya que esto indicaría algunas aplicaciones están utilizando todos los semáforos de un set y quizás necesitarían más semáforos de los que hemos establecido.
  • La suma de la columna NSEMS no esté demasiado cerca del valor del parámetro semsys:seminfo_semmns (SEMMNS), ya que si esto ocurre, podríamos tener problemas a la hora de crear nuevos sets de semáforos.

Utilizar MDB para ver los semáforos

Otra herramienta con la que podemos consultar el estado de los semáforos es mdb (Modular Debugger). Si no tiene experiencia utilizando el debugger de Solaris, sería interesante que echase un ojo al artículo Solaris: Buceando en el Kernel con mdb (I) donde se dan unas pinceladas sobre esta herramienta. Vamos a entrar en mdb y utilizaremos el comando ::ipcs.

 

(root@huelva_9)# mdb -k
Loading modules: [ unix krtld genunix emlxs ip s1394 usba ptm ipc random
md nfs logindmux nca cpc sppp ]
> ::ipcs
T    ID      KEY  MODE OWNER GROUP CREAT  CGRP             ADDR
m     0 00000c3b  0666     0     0     0     0 000003000877c000

...

m  2308 0f1ca610  0640   105   103   105   103 000003000877c440
T    ID      KEY  MODE OWNER GROUP CREAT  CGRP             ADDR
s     0 71b81609  0666     0     0     0     0 0000030006a430e8
s 65537 53b81108  0600     0     0     0     0 0000030006a43148
s     2 00000c3b  0666     0     0     0     0 0000030006a431a8
s 393219 00000c3c  0666     0     0     0     0 0000030006a43208
s     4 31b82002  0666     0     0     0     0 0000030006a43268
s     5 310001f7  0666     0     0     0     0 0000030006a432c8
s 65542 c9e03647  0644     0     0     0     0 0000030006a43328
s 165281799 a1866638  0640   105   103   105   103 0000030006a43388
s 27590664 a1866639  0640   105   103   105   103 0000030006a433e8
s 8781833 a186663a  0640   105   103   105   103 0000030006a43448
s 82575370 9ee686f8  0640   105   103   105   103 0000030006a434a8
s 12910603 9ee686f9  0640   105   103   105   103 0000030006a43508
s 3866636 9ee686fa  0640   105   103   105   103 0000030006a43568
s 31391757 6186af44  0640   105   103   105   103 0000030006a435c8
s 8126478 bd4cd75c  0640   105   103   105   103 0000030006a43628
s 983055 bd4cd75d  0640   105   103   105   103 0000030006a43688
s 4128784 bd4cd75e  0640   105   103   105   103 0000030006a436e8
s 27656209 55000a20  0666     0     0     0     0 0000030006a43748
>

El comando de mdb nos devuelve información de todos los IPCs que se están utilizando en el sistema, la primera columna muestra el tipo del IPC, una s nos indica que es un semáforo. La salida es muy parecida a la del comando del sistema operativo. La columna que nos interesa es ADDR que contiene la dirección de memoria de la estructura de datos semid_ds, que define el set de semáforos. La definición de esta estructura la podemos encontrar en el fichero de cabecera /usr/include/sys/sem.h

 

>
> 0000030006a43388::print -t "struct semid_ds"
{
    struct ipc_perm sem_perm = {
        uid_t uid = 0x69
        gid_t gid = 0x67
        uid_t cuid = 0x69
        gid_t cgid = 0x67
        mode_t mode = 0x81a0
        uint_t seq = 0x9da
        key_t key = 0xa1866638
    }
    struct sem *sem_base = 0x30014d5a970
    ushort_t sem_nsems = 0xfc
    time_t sem_otime = 0x467baff1
    time_t sem_ctime = 0x4675afa4
    int sem_binary = 0x1
    long [3] sem_pad3 = [ 0, 0, 0 ]
}
>

La estructura de tipo semid_ds está formada por los siguientes campos:

  • sem_perm, donde se definen los permisos del set de semáforos
  • sem_base, es la dirección del memoria del primer semáforo, de todos los que forman el set.
  • sem_nsems, el número de semáforos que tiene el set.

Vamos a ver el contenido de la dirección de memoria del primer semáforo del set, la dirección es 0x30014d5a970.

 

>
> 0x30014d5a970::print -t "struct sem"
{
    ushort_t semval = 0x1
    pid_t sempid = 0x1314
    ushort_t semncnt = 0
    ushort_t semzcnt = 0
    kcondvar_t semncnt_cv = {
        ushort_t _opaque = 0
    }
    kcondvar_t semzcnt_cv = {
        ushort_t _opaque = 0
    }
}
>

De la estructura de datos sem los campos interesantes son, sempid que contiene el PID del proceso que realizó la última operación en el semáforo y semval que contiene el valor del semáforo. Podemos utiliza el operador . (punto), para recorrer toda la lista de los semáforos que forman el set.

 

>
> .::print -t "struct sem"
{
    ushort_t semval = 0
    pid_t sempid = 0x131b
    ushort_t semncnt = 0x1
    ushort_t semzcnt = 0
    kcondvar_t semncnt_cv = {
        ushort_t _opaque = 0x1
    }
    kcondvar_t semzcnt_cv = {
        ushort_t _opaque = 0
    }
}
> .::print -t "struct sem"
{
    ushort_t semval = 0
    pid_t sempid = 0x131d
    ushort_t semncnt = 0x1
    ushort_t semzcnt = 0
    kcondvar_t semncnt_cv = {
        ushort_t _opaque = 0x1
    }
    kcondvar_t semzcnt_cv = {
        ushort_t _opaque = 0
    }
}
> .::print -t "struct sem"
{
    ushort_t semval = 0
    pid_t sempid = 0x131d
    ushort_t semncnt = 0x1
    ushort_t semzcnt = 0
    kcondvar_t semncnt_cv = {
        ushort_t _opaque = 0x1
    }
    kcondvar_t semzcnt_cv = {
        ushort_t _opaque = 0
    }
}
> .::print -t "struct sem"
{
    ushort_t semval = 0
    pid_t sempid = 0x131f
    ushort_t semncnt = 0x1
    ushort_t semzcnt = 0
    kcondvar_t semncnt_cv = {
        ushort_t _opaque = 0x1
    }
    kcondvar_t semzcnt_cv = {
        ushort_t _opaque = 0
    }
}
>

Semáforos en Solaris 10

Ya hemos comentado que la forma de configurar el número de sets de semáforos ha cambiado de Solaris 9 a Solaris 10, si ejecutamos el comando sysdef en Solaris 10 y buscamos la sección de IPC, veremos que nos indica que debemos leer el manual para ver como modificar estos parámetros desde el control de recursos.

 

(root@huelva_10)# sysdef
...
* IPC Semaphores
*
* The IPC Semaphores module no longer has system-wide limits.
* Please see the "Solaris Tunable Parameters Reference Manual" for
* information on how the old limits map to resource controls and
* the prctl(1) and getrctl(2) manual pages for information on
* observing the new limits.
*
*
* IPC Shared Memory
*
* The IPC Shared Memory module no longer has system-wide limits.
* Please see the "Solaris Tunable Parameters Reference Manual" for
* information on how the old limits map to resource controls and
* the prctl(1) and getrctl(2) manual pages for information on
* observing the new limits.
*
*
* Time Sharing Scheduler Tunables
*
60      maximum time sharing user priority (TSMAXUPRI)
SYS     system class name (SYS_NAME)
(root@huelva_10)#

Ahora los límites de los semáforos, número de sets, número de semáforos por set, número máximo de semáforos en el sistema, etc. En esta versión los límites de los semáforos los podemos aplicar a proyectos o procesos. Para ver como están configurados los límites de los semáforos mediante el control de recursos debemos utilizar el comando rctladm.

 

(root@huelva_10)# rctladm -l | grep sem
process.max-sem-ops         syslog=off     [ deny count ]
process.max-sem-nsems       syslog=off     [ deny count ]
project.max-sem-ids         syslog=off     [ no-basic deny count ]
(root@huelva_10)#

En la siguiente tabla podemos ver una relación entre los parámetros de Solaris 9 y nombres de los recursos que maneja el control de recursos.

Solaris 10 Solaris 9
process.max-sem-nsems semsys:seminfo_semmsl
project.max-sem-ids semsys:seminfo_semmni

En cuanto a las herramientas en Solaris 10 para consultar el estado de los semáforos, podemos utiliza ipcs y mdb (Modular Debugger), al igual que hemos visto para Solaris 9.

Nota - Si tiene alguna pregunta o sugerencia sobre este artículo, por favor, no dude en ponerse en contacto conmigo mediante email en jjmora AT arrakis DOT es

<< | >>

Technorati Tag(s) :

Los comentarios están cerrados.

My name is null, /dev/null
Algunos derechos reservados. Licencia Creative Commons