SlideShare una empresa de Scribd logo
1 de 167
Descargar para leer sin conexión
Gu´ Linux de Programaci´n (GULP)
            ıa                   o




                               Sven Goldt
                            Sven van der Meer
                              Scott Burkett
                               Matt Welsh

                                Versi´n 0.4
                                     o
                                Marzo 1995




  0
    ...Nuestro objetivo permanente: mejorar nuestro conocimiento de C, explorar
extra˜os comandos Unix y to boldly code where no one has man page 4.
      n
2
´
Indice General

1 El sistema operativo Linux                                                                9

2 El n´ cleo de Linux
      u                                                                                    11

3 El paquete libc de Linux                                                                 13

4 Llamadas al sistema                                                                      15

5 Una llamada multiuso: “ioctl”                                                            17

6 Comunicaci´n entre procesos en Linux
              o                                                                            19
  6.1 Introducci´n . . . . . . . . . . . . . . . . . . . . .
                o                                              .   .   .   .   .   .   .   19
  6.2 Pipes UNIX Semi-d´ plex . . . . . . . . . . . . .
                           u                                   .   .   .   .   .   .   .   19
      6.2.1 Conceptos b´sicos . . . . . . . . . . . . .
                          a                                    .   .   .   .   .   .   .   19
      6.2.2 Creaci´n de tuber´ en C . . . . . . . . .
                     o           ıas                           .   .   .   .   .   .   .   21
      6.2.3 Tuber´ la forma f´cil de hacerlo . . . .
                    ıas,           a                           .   .   .   .   .   .   .   27
      6.2.4 Operaciones at´micas con tuber´ . . . .
                              o                  ıas           .   .   .   .   .   .   .   31
      6.2.5 Notas acerca de las tuber´ semi-d´ plex:
                                         ıas         u         .   .   .   .   .   .   .   32
  6.3 Tuber´ con Nombre (FIFO - First In First Out)
            ıas                                                .   .   .   .   .   .   .   32
      6.3.1 Conceptos b´sicos . . . . . . . . . . . . .
                          a                                    .   .   .   .   .   .   .   32
      6.3.2 Creaci´n de una FIFO . . . . . . . . . . .
                     o                                         .   .   .   .   .   .   .   32
      6.3.3 Operaciones con FIFOs . . . . . . . . . .          .   .   .   .   .   .   .   34
      6.3.4 Acciones Bloqueantes en una FIFO . . . .           .   .   .   .   .   .   .   36
      6.3.5 La Infame Se˜ al SIGPIPE . . . . . . . . .
                            n                                  .   .   .   .   .   .   .   36
  6.4 IPC en Sistema V . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   36
      6.4.1 Conceptos fundamentales . . . . . . . . .          .   .   .   .   .   .   .   36
      6.4.2 Colas de Mensajes . . . . . . . . . . . . .        .   .   .   .   .   .   .   39
      6.4.3 Sem´foros . . . . . . . . . . . . . . . . . .
                  a                                            .   .   .   .   .   .   .   57
      6.4.4 Memoria Compartida . . . . . . . . . . .           .   .   .   .   .   .   .   77

7 Programaci´n del Sonido
             o                                                         87
  7.1 Programaci´n del altavoz interno . . . . . . . . . . . . . . . . 87
                o
  7.2 Programaci´n de una Tarjeta de sonido . . . . . . . . . . . . 88
                o

                                      3
4                                                         ´
                                                          INDICE GENERAL

8 Gr´ficos en modo car´cter
     a                       a                                                                  89
  8.1 Funciones E/S en la libc . . . . . . . . . . . . .       .   .   .   .   .   .   .   .    90
       8.1.1 Salida con Formato . . . . . . . . . . . .        .   .   .   .   .   .   .   .    90
       8.1.2 Entrada con Formato . . . . . . . . . .           .   .   .   .   .   .   .   .    92
  8.2 La Librer´ Termcap . . . . . . . . . . . . . . .
                  ıa                                           .   .   .   .   .   .   .   .    94
       8.2.1 Introducci´n . . . . . . . . . . . . . . .
                           o                                   .   .   .   .   .   .   .   .    94
       8.2.2 Encontrar la descripci´n del terminal . .
                                       o                       .   .   .   .   .   .   .   .    94
       8.2.3 Lectura de una descripci´n de terminal
                                          o                    .   .   .   .   .   .   .   .    95
       8.2.4 Capacidades de Termcap . . . . . . . .            .   .   .   .   .   .   .   .    96
  8.3 Ncurses - Introducci´n . . . . . . . . . . . . . .
                               o                               .   .   .   .   .   .   .   .   101
  8.4 Inicializaci´n . . . . . . . . . . . . . . . . . . .
                   o                                           .   .   .   .   .   .   .   .   103
  8.5 Ventanas . . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   104
  8.6 Salida . . . . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   107
       8.6.1 Salida con Formato . . . . . . . . . . . .        .   .   .   .   .   .   .   .   109
       8.6.2 Inserci´n de Caracteres/L´
                      o                     ıneas . . . . .    .   .   .   .   .   .   .   .   109
       8.6.3 Borrado de Caracteres/L´      ıneas . . . . . .   .   .   .   .   .   .   .   .   110
       8.6.4 Cajas y L´   ıneas . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   110
       8.6.5 Car´cter de Fondo . . . . . . . . . . . .
                    a                                          .   .   .   .   .   .   .   .   112
  8.7 Entrada . . . . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   112
       8.7.1 Entrada con Formato . . . . . . . . . .           .   .   .   .   .   .   .   .   113
  8.8 Opciones . . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   114
       8.8.1 Opciones en la entrada . . . . . . . . . .        .   .   .   .   .   .   .   .   114
       8.8.2 Atributos de la terminal . . . . . . . . .        .   .   .   .   .   .   .   .   116
       8.8.3 ¿C´mo se usa? . . . . . . . . . . . . . .
                   o                                           .   .   .   .   .   .   .   .   117
  8.9 ¿C´mo borrar ventanas y l´
          o                         ıneas? . . . . . . . .     .   .   .   .   .   .   .   .   119
  8.10 Actualizaci´n de la imagen an la terminal . . .
                    o                                          .   .   .   .   .   .   .   .   120
  8.11 Atributos de v´ ıdeo y colores . . . . . . . . . . .    .   .   .   .   .   .   .   .   122
  8.12 Coordenadas del cursor y de las ventanas . . .          .   .   .   .   .   .   .   .   126
  8.13 Movi´ndonos por all´ . . . . . . . . . . . . . . .
            e                  ı                               .   .   .   .   .   .   .   .   127
  8.14 Pads . . . . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   129
  8.15 Soft-labels . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   129
  8.16 Miscel´nea . . . . . . . . . . . . . . . . . . . .
              a                                                .   .   .   .   .   .   .   .   130
  8.17 Acceso de Bajo Niv´l . . . . . . . . . . . . . . .
                              e                                .   .   .   .   .   .   .   .   131
  8.18 Volcado de Pantalla . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   131
  8.19 Emulaci´n Termcap . . . . . . . . . . . . . . .
                o                                              .   .   .   .   .   .   .   .   131
  8.20 Funciones Terminfo . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   132
  8.21 Funciones de Depurado . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   133
  8.22 Atributos Terminfo . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   133
       8.22.1 Atributos L´gicos . . . . . . . . . . . . .
                             o                                 .   .   .   .   .   .   .   .   133
       8.22.2 N´ meros . . . . . . . . . . . . . . . . . .
                 u                                             .   .   .   .   .   .   .   .   134
       8.22.3 Cadenas . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   135
  8.23 Esquema de las Funciones de [N]Curses . . . .           .   .   .   .   .   .   .   .   143
´
INDICE GENERAL                                                                                               5

9 Programaci´n de los Puertos de
             o                             E/S                                                             147
  9.1 Programaci´n del Rat´n . . . .
                o          o               . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   149
  9.2 Programaci´n del M´dem . . .
                o        o                 . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   150
  9.3 Programaci´n de la Impresora .
                o                          . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   150
  9.4 Programaci´n del Joystick . . .
                o                          . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   150

10 Conversi´n de Aplicaciones a Linux
             o                                                                                             151
   10.1 Introducci´n . . . . . . . . . . . . . . . . . .
                  o                                                .   .   .   .   .   .   .   .   .   .   151
   10.2 Gesti´n de Se˜ ales . . . . . . . . . . . . . .
             o        n                                            .   .   .   .   .   .   .   .   .   .   152
        10.2.1 Se˜ ales en SVR4, BSD, y POSIX.1 .
                  n                                                .   .   .   .   .   .   .   .   .   .   152
        10.2.2 Opciones de Se˜ ales en Linux . . . .
                                n                                  .   .   .   .   .   .   .   .   .   .   153
        10.2.3 signal en Linux . . . . . . . . . . . .             .   .   .   .   .   .   .   .   .   .   154
        10.2.4 Se˜ ales soportadas por Linux . . . .
                  n                                                .   .   .   .   .   .   .   .   .   .   154
   10.3 E/S de Terminal . . . . . . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   154
   10.4 Control e Informaci´n de Procesos . . . . .
                             o                                     .   .   .   .   .   .   .   .   .   .   155
        10.4.1 Rutinas kvm . . . . . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   156
        10.4.2 ptrace y el sistema de ficheros /proc                .   .   .   .   .   .   .   .   .   .   156
        10.4.3 Control de Procesos en Linux . . . .                .   .   .   .   .   .   .   .   .   .   156
   10.5 Compilaci´n Condicional Portable . . . . .
                  o                                                .   .   .   .   .   .   .   .   .   .   157
   10.6 Comentarios Adicionales . . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   159

11 Llamadas al sistema en orden alfab´tico
                                     e                                                                     161

12 Abreviaturas                                                                                            167
• Copyright
  La Gu´ Linux de Programaci´n es c 1994, 1995 de Sven Goldt
         ıa                      o
  Sven Goldt, Sachsendamm 47b, 10829 Berl´ Alemania
                                            ın,
  < goldt@math.tu − berlin.de > .
  El cap´  ıtulo 8 es c 1994, 1995 de Sven van der Meer
  < vdmeer@cs.tu − berlin.de > .
  El cap´ıtulo 6 es c 1995 de Scott Burkett < scottb@IntN et.net > .
  El cap´   ıtulo 10 es c 1994, 1995 de Matt Welsh <
  mdw@cs.cornell.edu > .
  Tenemos que dar especialmente las gracias a John D. Harper
  < jharper@uiuc.edu > por revisar en profundidad esta gu´ ıa.
  Se concede permiso para reproducir este documento, en todo o en
  parte, bajo las siguientes condiciones:

    1. Esta nota de Copyright debe incluirse sin modificaciones.
    2. Comparta con los autores cualquier ganancia que obtenga.
    3. Los autores no se hacen responsables de cualquier da˜ o producido
                                                           n
       en aplicaci´n de los contenidos de este libro.
                  o

• Copyright (nota original)
  The Linux Programmer’s Guide is c 1994, 1995 by Sven Goldt
  Sven Goldt, Sachsendamm 47b, 10829 Berlin, Germany
  < goldt@math.tu − berlin.de > .
  Chapter 8 is c 1994, 1995 by Sven van der Meer < vdmeer@cs.tu −
  berlin.de > .
  Chapter 6 is c 1995 Scott Burkett < scottb@IntN et.net > .
  Chapter 10 is c 1994, 1995 Matt Welsh < mdw@cs.cornell.edu > .
  Special thanks goes to John D. Harper < jharper@uiuc.edu > for
  proofreading this guide.
  Permission to reproduce this document in whole or in part is subject
  to the following conditions:

    1. The copyright notice remains intact and is included.
    2. If you make money with it the authors want a share.
    3. The authors are not responsible for any harm that might arise by
       the use of it.

• Notas sobre la versi´n castellana
                      o
  Esta gu´ como cuarto trabajo importante del Proyecto LuCAS, obe-
          ıa,
  dece a la demanda de gu´ de programaci´n para Unix/Linux que ve-
                          ıas              o
  nimos observando desde tiempos recientes. Sin embargo, lamentamos
  que nuestra traducci´n sea tan incompleta como la versi´n original en
                       o                                 o
  Ingl´s: ciertamente nos gustar´ completarla, sin embargo no hemos
      e                          ıa

                                 6
´
INDICE GENERAL                                                                       7

         podido recibir los permisos necesarios para ello de algunos de sus au-
         tores originales, al estar actualmente ilocalizables. El proyecto LuCAS
         agradece el trabajo de traducci´n realizado inicialmente por Pedro Pa-
                                            o
         blo F´brega
               a      1 , que abarca buena parte del libro. Adem´s, agradecemos
                                                                  a
         la colaboraci´n prestada por Ignacio Arenaza, C´sar Ballardini y Luis
                       o                                    e
         Francisco Gonz´lez2 , quienes se han ocupado de la traducci´n del resto
                           a                                           o
         del libro.
         Nota: Versi´n de la traducci´n: 0.11 alpha
                       o                  o
         Juan Jos´ Amor
                   e         3 , Mayo de 1998.


       • Pr´logo
            o
         Esta gu´ est´ lejos de completarse.
                  ıa   a
         La primera edici´n fue la versi´n 0.1, de septiembre de 1994. Se bas´ en
                          o             o                                        o
         las llamadas al sistema debido a la escased de informaci´n al respecto.
                                                                   o
         Est´ previsto completarla con la descripci´n de las funciones de librer´
             a                                       o                              ıa
         y cambios importantes en el n´ cleo, as´ como incursiones en areas
                                           u         ı                         ´
         como redes, sonido, gr´ficos y entrada/salida as´
                                a                          ıncrona. As´  ımismo, se
         incluir´n en un futuro apuntes sobre c´mo construir librer´ din´micas
                a                               o                    ıas     a
         y acerca de interesantes herramientas para el programador.
         Esta gu´ solo ser´ un ´xito gracias a la ayuda en forma de informaci´n
                  ıa        a   e                                                  o
         o de env´ de nuevos cap´
                   ıo              ıtulos.

       • Introducci´n
                    o
         En cierta ocasi´n me dispuse a instalar Linux en mi PC para aprender
                         o
         m´s acerca de administraci´n del sistema. Intent´ instalar un servidor
           a                         o                     e
         de SLIP pero no trabaj´ con mgetty ni con el shadow. Tuve que par-
                                  e
         chear el sliplogin y funcion´ hasta las nuevas versiones de Linux 1.1.
                                      o
         Nadie me explic´ qu´ hab´ pasado. No hab´ documentaci´n acer-
                           o   e     ıa                 ıa             o
         ca de los cambios desde el n´ cleo 0.99 salvo los res´ menes que hac´
                                        u                     u              ıa
         Russ Nelson, si bien ´stos no me ayudaban demasiado a resolver mis
                                e
         problemas.
         La Gu´ Linux de Programaci´n pretende servir para lo que su nombre
                ıa                    o
         implica— para ayudar al programador de Linux a entender las pecu-
         liaridades de este sistema operativo. Tambi´n deber´ ser util para
                                                       e        a    ´
         transportar programas de otros sistemas operativos al Linux. Por lo
         tanto, esta gu´ debe describir las llamadas al sistema y los cambios
                       ıa
         importantes del n´ cleo que puedan afectar a antiguos programas tales
                           u
         como aplicaciones de E/S serie o de red.

       Sven Goldt Gu´ Linux de Programaci´n
                    ıa                   o

   1
      Pedro Pablo est´ disponible en pfabrega@arrakis.es
                     a
   2
      Sus direcciones de correo respectivas son:           inaki.arenaza@jet.es,   cba-
llard@santafe.com.ar y luisgh@cogs.susx.ac.uk
    3
      Como siempre, en jjamor@ls.fi.upm.es
8   ´
    INDICE GENERAL
Cap´
   ıtulo 1

El sistema operativo Linux

En marzo de 1991 Linus Benedict Torvalds compr´ un sistema Multitarea
                                                   o
Minix para su AT. Lo us´ para desarrollar su propio sistema multitarea que
                        o
llam´ Linux. En el mes septiembre de 1991 liber´ el primer prototipo por e-
    o                                           o
mail a algunos otros usuarios de Minix en Internet: as´ comenz´ el proyecto
                                                      ı        o
Linux. Muchos programadores desde ese punto han apoyado Linux. Han
agregado controladores de dispositivos, desarrollado aplicaciones, seg´ n las
                                                                      u
normas POSIX. Hoy Linux es muy potente, pero lo mejor es que es gratuito.
Se est´n realizando trabajos para transportar Linux a otras plataformas.
      a




                                     9
10   CAP´
        ITULO 1. EL SISTEMA OPERATIVO LINUX
Cap´
   ıtulo 2

El n´cleo de Linux
    u

La base de Linux es el n´ cleo. Podr´ reemplazar todas las librer´ pero
                          u           ıa                             ıas,
mientras quede el n´ cleo, estar´ todav´ Linux. El n´ cleo incorpora contro-
                    u           a       ıa            u
ladores de dispositivos, manejo de la memoria, manejo de procesos y manejo
de comunicaciones. Los gur´ s del n´ cleo siguen las pautas POSIX que hacen
                            u       u
la programaci´n a veces m´s f´cil y a veces m´s dif´
              o             a a                 a     ıcil. Si su programa se
comporta de forma diferente en un nuevo n´ cleo de Linux, puede ser porque
                                             u
se hayan implantado nuevas l´ ıneas marcadas por POSIX. Para m´s informa-
                                                                   a
ci´n de la programaci´n sobre el n´ cleo de Linux, lea el documento Linux
  o                    o            u
Kernel Hacker’s Guide.




                                     11
12   CAP´            ´
        ITULO 2. EL NUCLEO DE LINUX
Cap´
   ıtulo 3

El paquete libc de Linux

      libc: ISO 8859.1, < linux/param.h >, funciones YP, funciones crypt,
      algunas rutinas shadow b´sicas (por omisi´n no incluidas),... rutinas
                                a                  o
      viejas por compatibilidad en libcompat (por omisi´n no activas),
                                                           o
      mensajes del error en ingl´s, franc´s o alem´n, rutinas de gesti´n de
                                 e         e         a                 o
      la pantalla compatibles bsd 4.4lite en libcurses, rutinas compatibles
      bsd en libbsd, rutinas de la manipulaci´n de la pantalla en
                                                o
      libtermcap, rutinas del manejo del base de datos en libdbm, rutinas
      matem´ticas en libm, entradas para ejecutar programas en crt0.o???,
              a
      informaci´n del sexo del byte en libieee??? (¿pod´ alguien dar
                o                                         ıa
      informaci´n en lugar de re´
                o                 ırse?), espacio de perfiles de usuario, en
      libgmon. Me gustar´ que alguno de los desarrolladores de la librer´
                          ıa                                                ıa
      libc de Linux escribiera este cap´ ıtulo. Todo lo que puedo decir ahora
      es que va ha haber un cambio del formato de ejecutables a.out a elf
      (formato ejecutable y enlazable) que tambi´n significa un cambio en la
                                                    e
      construcci´n de bibliotecas compartidas. Normalmente se soportan am-
                 o
bos
      formatos, a.out y elf
      La mayor´ de los elementos del paquete libc de Linux est´n bajo la
                ıa                                                a
Licencia P´ blica GNU, aunque algunos est´n bajo una excepci´n especial
              u                               a                   o
de derechos de copia como crt0.o. Para distribuciones comerciales binarias
esto significa una restricci´n que prohibe el enlace est´tico de ejecutables.
                             o                          a
El enlace din´mico de ejecutables son de nuevo una excepci´n especial y
                a                                              o
Richard Stallman del FSF coment´:   o
[. . . ] Pero me parece que debemos permitir de forma ambigua la distribuci´n
                                                                           o
de ejecutables enlazados din´micamente *sin* ir acompa˜ados de la librer´as
                             a                          n                 ı
bibliotecas, con tal de que los ficheros objeto que forman el ejecutable est´n
                                                                           e
sin restricci´n seg´n la secci´n 5 [. . . ] Por tanto tomar´ la decisi´n de
             o      u           o                           e          o
permitirlo. La actualizaci´n del LGPL tendr´ que esperar hasta que tenga
                           o                   a
tiempo para hacer y comprobar una versi´n nueva.
                                           o
    Sven Goldt Gu´ Linux de Programaci´n
                    ıa                       o

                                       13
14   CAP´
        ITULO 3. EL PAQUETE LIBC DE LINUX
Cap´
   ıtulo 4

Llamadas al sistema

Una llamada al sistema es normalmente una demanda al sistema operati-
vo (nucleo) para que haga una operaci´n de hardware/sistema espec´
                                      o                               ıfica o
privilegiada. Por ejemplo, en Linux-1.2, se han definido 140 llamadas al
sistema. Las llamadas al sistema como close() se implementan en la libc
de Linux. Esta aplicaci´n a menudo implica la llamada a una macro que
                        o
puede llamar a syscall(). Los par´metros pasados a syscall() son el n´ mero
                                 a                                    u
de la llamada al sistema seguida por el argumento necesario. Los n´ meros
                                                                     u
de llamadas al sistema se pueden encontrar en < linux/unistd.h > mientras
que < sys/syscall.h > actualiza con una nueva libc. Si aparecen nuevas lla-
madas que no tienen una referencia en libc aun, puede usar syscall(). Como
ejemplo, puede cerrar un fichero usando syscall() de la siguiente forma (no
aconsejable):

#include <syscall.h>

extern int syscall(int, ...);

int my_close(int filedescriptor)
{
   return syscall(SYS_close, filedescriptor);
}

     En la arquitectura i386, las llamadas al sistema est´n limitadas a 5 ar-
                                                         a
gumentos adem´s del n´ mero de llamada al sistema debido al n´ mero de
                 a       u                                         u
registros del procesador. Si usa Linux en otra arquitectura puede compro-
bar el contenido de < asm/unistd.h > para las macros syscall, para ver
cu´ntos argumentos admite su hardware o cuantos escogieron los desarro-
   a
lladores. Estas macros syscall se pueden usar en lugar de syscall(), pero
esto no se recomienda ya que esa macro se expande a una funci´n que ya
                                                                   o
puede existir en una biblioteca. Por consiguiente, s´lo los desarrolladores
                                                      o

                                     15
16                            CAP´
                                 ITULO 4. LLAMADAS AL SISTEMA

del n´ cleo deber´ jugar a con las macros syscall. Como demostraci´n,
      u          ıan                                              o
aqu´ tenemos el ejemplo de close() usando una macro syscall.
    ı

#include <linux/unistd.h>

_syscall1(int, close, int, filedescriptor);

La macro syscall1 expande la funci´n close(). As´ tenemos close() dos veces,
                                     o             ı
una vez en libc y otra vez en nuestro programa. El valor devuelto por
syscall() o un una macro syscall es -1 si la llamada al sistema fall´ y 0 en
                                                                    o
caso de ´xito. D´le un vistazo a la variable global errno para comprobar que
         e       e
ha ocurrido si la llamada al sistama fall´.
                                         o
    Las siguiente llamadas al sistema est´n disponibles en BSD y SYS V
                                            a
pero no est´n disponibles en Linux:
            a
audit(), auditon(), auditsvc(), fchroot(), getauid(), getdents(), getmsg(),
mincore(), poll(), putmsg(), setaudit(), setauid().
    Sven Goldt Gu´ Linux de Programaci´n
                    ıa                       o
Cap´
   ıtulo 5

Una llamada multiuso:
“ioctl”

ioctl representa el control de entrada/salida y se usa para manipular un
dispositivo de car´cter mediante un descriptor de fichero. El formato de
                     a
ioctl es:
ioctl(unsigned int fd, unsigned int request, unsigned long argument).
El valor devuelto es -1 si ocurri´ un error y un valor mayor o igual que 0 si
                                 o
la petici´n tuvo ´xito, como cualquier otra llamadas del sistema. El n´ cleo
          o        e                                                   u
distingue entre ficheros especiales y regulares. Los ficheros especiales se
encuentran principalmente en /dev y /proc. Difieren de los ficheros regulares
en que esconden una interface a un controlador y no un fichero real (regular)
que contiene texto o datos binarios. Esta es la filosof´ UNIX y permite usar
                                                      ıa
operaciones normales de lectura/escritura en cada fichero. Pero si necesita
hacer algo m´s con un fichero especial o un fichero regular que puede hacer
               a
´l con... s´ ioctl. Usted necesitar´ con m´s frecuencia ioctl para ficheros
e           ı,                      a        a
especiales que para ficheros regulares, pero es posible usar ioctl en ficheros
regulares tambi´n.
                 e




                                     17
18   CAP´
        ITULO 5. UNA LLAMADA MULTIUSO: “IOCTL”
Cap´
   ıtulo 6

Comunicaci´n entre procesos
          o
en Linux

B. Scott Burkett, scottb@intnet.net v1.0, 29 de Marzo de 1995


6.1     Introducci´n
                  o
Los medios IPC (Inter-process communication) de Linux proporcionan un
m´todo para que m´ ltiples procesos se comuniquen unos con otros. Hay
  e                 u
varios m´todos de IPC disponibles para los programadores Linux en C:
        e
   • Pipes UNIX Half-duplex
   • FIFOs (pipes con nombre)
   • Colas de mensajes estilo SYSV
   • Sem´foros estilo SYSV
        a
   • Segmentos de memoria compartida estilo SYSV
   • Sockets (estilo Berkeley) (no contemplado por ahora)
   • Pipes Full-duplex (pipes STREAMS) (no contemplado por ahora)
    Estos medios, cuando se usan de forma efectiva, proporciona una ba-
se s´lida para el desarrollo de cliente/servidor en cualquier sistema UNIX
    o
(incluido Linux).


6.2     Pipes UNIX Semi-d´ plex
                         u
6.2.1   Conceptos b´sicos
                   a
Simplemente, una tuber´ (pipe) es un m´todo de conexi´n de que une la
                       ıa                e              o
salida est´ndar de un proceso a la entrada est´ndar de otro. Las tuber´
          a                                   a                       ıas

                                   19
20    CAP´                  ´
         ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

son la mayor de las herramientas de IPC, han estado presentes desde los
primeros or´
           ıgenes del sistema operativo UNIX. Proporcionan un m´todo de
                                                                  e
comunicaciones en un sentido (unidirecional, semi-duplex) entre procesos.
   Este mecanismo es ampliamente usado, incluso en la l´ınea de comandos
UNIX (en la shell):

               ls | sort | lp

    Lo anterior es un ejemplo de ’pipeline’, donde se toma la salida de un
comando ls como entrada de un comando sort, quien a su vez entrega su
salida a la entrada de lp. Los datos corren por la tuber´ semi-duplex, de
                                                            ıa
viajando (virtualmente) de izquierda a derecha por la tuber´   ıa.
    Aunque la mayor parte de nosotros usamos las tuber´ casi religiosa-
                                                             ıas
mente en las programaciones de scripts de shell, casi nunca nos paramos a
pensar en lo que tiene lugar a nivel del n´ cleo.
                                            u
    Cuando un proceso crea una tuber´ el n´ cleo instala dos descriptores
                                         ıa,    u
de ficheros para que los use la tuber´ Un descriptor se usa para permitir
                                      ıa.
un camino de entrada a la tuber´ (write), mientras que la otra se usa para
                                  ıa
obtener los datos de la tuber´ (read). A estas alturas, la tuber´ tiene un
                              ıa                                   ıa
peque˜ o uso pr´ctico, ya que la creaci´n del proceso s´lo usa la tuber´ para
      n         a                      o               o               ıa
comunicarse consigo mismo. Considere esta representaci´n de un proceso y
                                                           o
del n´ cleo despu´s de que se haya creado una tuber´
     u            e                                  ıa:


                      in
     Proceso                                           Nucleo
                      out




     Del diagrama anterior, es f´cil ver c´mo se conectan los descriptores. Si
                                a          o
el proceso env´ datos por la tuber´ (fd0), tiene la habilidad obtener (leer)
                ıa                   ıa
esa informaci´n de fd1. Sin embargo, hay un objetivo m´s amplio sobre
               o                                              a
el esquema anterior. Mientras una tuber´ conecta inicialmente un proceso
                                             ıa
a s´ mismo, los datos que viajan por la tuber´ se mueven por el n´ cleo.
    ı                                            ıa                     u
Bajo Linux en particular, las tuber´ se representan realmente de forma
                                       ıas
interna con un inodo v´lido. Por supuesto, este inodo reside dentro del
                         a
n´ cleo mismo, y no dentro de los l´
  u                                   ımites de cualquier sistema de archivos
f´
 ısico. Este punto particular nos abrir´ algunas puertas de E/S bastante
                                           a
pr´cticas, como veremos un poco m´s adelante.
   a                                  a
     A estas alturas, la tuber´ es bastante in´ til. Despu´s de todo ¿por
                               ıa                u            e
qu´ el problema de crear una ca˜ er´ si estamos s´lo hablando con nosotros
   e                              n ıa              o
´
6.2. PIPES UNIX SEMI-DUPLEX                                                21

mismos? Ahora, el proceso de creaci´n bifurca un proceso hijo. Como
                                        o
un proceso hijo hereda cualquier descriptor de fichero abierto del padre,
ahora tenemos la base por comunicaci´n multiprocesos (entre padre e hijo).
                                      o
Considere ´ste versi´n actualizada de de nuestro esquema simple:
          e         o


             in                                           in
 Proceso                         Nucleo                         Proceso
 Padre                                                              Hijo
            out                                           out




    Arriba, vemos que ambos procesos ahora tienen acceso al descriptor del
fichero que constituye la tuber´ Est´ en esa fase, que se debe tomar una de-
                               ıa.    a
cisi´n cr´
    o    ıtica. ¿En que direcci´n queremos que viajen los datos? ¿El proceso
                               o
hijo env´ informaci´n al padre, o viceversa? Los dos procesos mutuamen-
         ıa          o
te est´n de acuerdo en esta emisi´n, y procede a“cerrar” el extremo de la
      a                            o
ca˜ er´ que no le interesa. Por motivos discusi´n, digamos que el hijo ejecu-
   n ıa                                        o
ta unos procesos, y devuelve informaci´n por la tuber´ al padre. Nuestro
                                        o               ıa
esquema ya revisado aparecer´ como:
                               ıa


             in                                           in
 Proceso                         Nucleo                         Proceso
 Padre                                                              Hijo
            out                                           out




    ¡Ahora la construcci´n de la tuber´ est´ completa! Lo unico que queda
                        o               ıa a              ´
por hacer es usar la tuber´ Para a acceder a una tuber´ directamente,
                           ıa.                            ıa
podemos usar la misma llamada al sistema que se usa para un fichero I/O de
bajo nivel. (las tuber´ est´n representadas internamente como un inodo
                      ıas    a
v´lido).
  a
    Para enviarle datos a la tuber´ usamos la llamada al sistema write(),
                                   ıa,
y para recuperar datos de la tuber´ usamos la llamada al sistema read().
                                    ıa,
¡Recuerde las llamadas del sistema a los ficheros I/O de bajo-nivel se hacen
usando descriptores de fichero! Sin embargo, tenga presente que ciertas
llamadas al sistema, como por ejemplo lseek(), no trabaja con descriptores
a tuber´ıas.

6.2.2   Creaci´n de tuber´ en C
              o          ıas
Crear “tuber´
            ıas” con el lenguaje de programaci´n C puede ser un poco m´s
                                              o                       a
complejo que en un ejemplo de shell. Para crear una tuber´ simple con C,
                                                         ıa
22     CAP´                  ´
          ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

hacemos uso de la llamada al sistema pipe(). Toma un argumento solo, que
es una tabla de dos enteros, y si tiene ´xito, la tabla contendr´ dos nuevos
                                        e                       a
descriptores de ficheros para ser usados por la tuber´ Despu´s de crear
                                                        ıa.       e
una tuber´ el proceso t´
           ıa,           ıpicamente desdobla a un proceso nuevo (recuerde
que el hijo hereda los descriptores del fichero).

     LLAMADA AL SISTEMA: pipe();

     PROTOTIPO: int pipe( int fd[2] );
       RETORNA: 0 si exito
                      ´
                -1 si error: errno = EMFILE (no quedan descriptores libres)
                                     EMFILE (tabla de ficheros del sistema llena)
                                     EFAULT (el vector fd no es v´lido)
                                                                 a

     NOTAS: fd[0] es para leer, fd[1] es para escribir

    El primer del vector fd (elemento 0) est´ fijado y abierto para lectura,
                                            a
mientras el segundo entero (elemento 1) est´ fijado y abierto para escritura.
                                           a
Visualmente hablando, la salida de fd1 se vuelve la entrada para fd0. Una
vez m´s, todo datos que se mueven por la tuber´ los hacen por el n´ cleo.
      a                                         ıa                   u

          #include <stdio.h>
          #include <unistd.h>
          #include <sys/types.h>

          main()
          {
                   int       fd[2];

                   pipe(fd);
                   .
                   .
          }

   Recuerde que un nombre de vector en C es un puntero a su primer
miembro. Es decir, fd es equivalente a &fd0. Una vez hemos establecido la
tuber´ entonces desdoblamos (fork) nuestro nuevo proceso hijo:
     ıa,

          #include <stdio.h>
          #include <unistd.h>
          #include <sys/types.h>

          main()
          {
´
6.2. PIPES UNIX SEMI-DUPLEX                                                23

                   int       fd[2];
                   pid_t     childpid;

                   pipe(fd);

                   if((childpid = fork()) == -1)
                   {
                           perror("fork");
                           exit(1);
                   }
                   .
                   .
         }

    Si el padre quiere recibir datos del hijo, debe cerrar fd1, y el hijo debe
cerrar fd0. Si el padre quiere enviarle datos al hijo, debe cerrar fd0, y el
hijo debe cerrar fd1. Como los descriptores se comparten entre el padre
y hijo, siempre debemos estar seguros cerrar el extremo de ca˜ er´ que no
                                                                 n ıa
nos interesa. Como nota t´cnica, nunca se devolver´ EOF si los extremos
                            e                         a
innecesarios de la tuber´ no son explicitamente cerrados.
                         ıa

         #include <stdio.h>
         #include <unistd.h>
         #include <sys/types.h>

         main()
         {
                   int       fd[2];
                   pid_t     childpid;

                   pipe(fd);

                   if((childpid = fork()) == -1)
                   {
                           perror("fork");
                           exit(1);
                   }

                   if(childpid == 0)
                   {
                           /* El hijo cierra el descriptor de entrada */
                           close(fd[0]);
                   }
                   else
24   CAP´                  ´
        ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

                  {
                           /* El padre cierra el descriptor de salida */
                           close(fd[1]);
                  }
                  .
                  .
         }

   Como se mencion´ previamente, una vez se ha establecido la tuber´ los
                     o                                              ıa,
descriptores de fichero se tratan como descriptores a ficheros normales.


/*****************************************************************************
 Parte de la "Guia Linux de Programacion - Capitulo 6"
 (C)opyright 1994-1995, Scott Burkett
 *****************************************************************************
 MODULO: pipe.c
 *****************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
        int       fd[2], nbytes;
        pid_t     childpid;
        char      string[] = "Hola a todos!n";
        char      readbuffer[80];

         pipe(fd);

         if((childpid = fork()) == -1)
         {
                 perror("fork");
                 exit(1);
         }

         if(childpid == 0)
         {
                 /* Cierre del descriptor de entrada en el hijo */
                 close(fd[0]);

                  /* Enviar el saludo via descriptor de salida */
´
6.2. PIPES UNIX SEMI-DUPLEX                                               25

                   write(fd[1], string, strlen(string));
                   exit(0);
          }
          else
          {
                   /* Cierre del descriptor de salida en el padre               */
                   close(fd[1]);

                   /* Leer algo de la tuberia... el saludo! */
                   nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                   printf("Received string: %s", readbuffer);
          }

          return(0);
}

    A menudo, los descriptores del hijo son duplicados en la entrada o salida
est´ndares. El hijo puede entonces hacer exec() con otro programa, que
   a
hereda los stream est´ndar. Observe la llamada al sistema dup():
                     a

    LLAMADA AL SISTEMA: dup();

    PROTOTIPO: int dup( int oldfd );
      RETORNA: nuevo descriptor si hay exito
                                        ´
               -1 si error: errno = EBADF (oldfd no es un descriptor valido)
                                     EBADF (newfd se sale del rango)
                                     EMFILE (Hay demasiados descriptores en el proceso abie

    NOTAS: <el antiguo descriptor no se cierra! Asi podemos intercambiarlos

    Aunque el descriptor viejo y el reci´n creado se puede intercambiar,
                                         e
normalmente cerraremos primero uno de los stream est´ndar. La llamada al
                                                      a
sistema dup() usa el n´ mero descriptor m´s bajo no utilizado para el nuevo
                       u                  a
descriptor.
    Considere lo siguiente:

          .
          .
          childpid = fork();

          if(childpid == 0)
          {
                  /* Cerrar la entrada estandar en el hijo */
                  close(0);
26     CAP´                  ´
          ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX



                    /* Duplicar sobre esta la salida de la tuberia */
                    dup(fd[0]);
                    execlp("sort", "sort", NULL);

          }

    Como el descriptor de fichero 0 (stdin) se cerr´, la llamada a dup()
                                                      o
duplic´ el descriptor de la entrada de la tuber´ (fd0) hacia su entrada
       o                                         ıa
est´ndar. Entonces hacemos una llamada a execlp() recubrir el segmento
   a
de texto (c´digo) del hijo con el del programa. ¡Desde no hace mucho los
            o
programas exec heredan los stream est´ndares de sus or´
                                         a               ıgenes, realmente
hereda el lado de la entrada de la tuber´ como su entrada est´ndar! Ahora,
                                        ıa                   a
cualquier cosa que el padre original procesa lo env´ a la tuber´ va en la
                                                    ıa         ıa,
facilidad de la clase.
    Hay otra llamada al sistema, dup2 (), que se puede usar tambi´n. Esta
                                                                   e
llamada particular tiene su origen con la Versi´n 7 de UNIX, se realiz´ por
                                               o                      o
una versi´n de BSD y ahora es requerida por el est´ndar POSIX.
          o                                         a

     LLAMADA AL SISTEMA: dup2();

     PROTOTIPO: int dup2( int oldfd, int newfd );
       RETORNA: nuevo descriptor si hay exito
                                        ´
                -1 si error: errno = EBADF (oldfd no es descriptor v´lido)
                                                                    a
                                     EBADF (newfd est´ fuera de rango)
                                                     a
                                     EMFILE (demasiados descriptores abiertos)

     NOTAS: <el descriptor antiguo es cerrado con dup2()!

    Con esta particular llamada, tenemos la operaci´n de cerrado, y la du-
                                                      o
plicaci´n del descriptor actual, relacionado con una llamada al sistema.
       o
Adem´s, se garantiza el ser at´mica, que esencialmente significa que nunca
       a                       o
se interrumpir´ por la llegada de una se˜ al. Toda la operaci´n transcurrir´
               a                          n                   o               a
antes de devolverle el control al n´ cleo para despachar la se˜ al. Con la lla-
                                   u                          n
mada al sistema dup() original, los programadores ten´ que ejecutar un
                                                         ıan
close() antes de llamarla. Esto resultaba de dos llamadas del sistema, con
un grado peque˜ o de vulnerabilidad en el breve tiempo que transcurre entre
                n
ellas. Si llega una se˜ al durante ese tiempo, la duplicaci´n del descriptor
                      n                                     o
fallar´ Por supuesto, dup2 () resuelve este problema para nosotros.
      ıa.
    Considere:

          .
          .
          childpid = fork();
´
6.2. PIPES UNIX SEMI-DUPLEX                                                27



         if(childpid == 0)
         {
                 /* Cerrar entrada estandar, duplicando a esta la
                    salida de datos de la tuberia */
                 dup2(0, fd[0]);
                 execlp("sort", "sort", NULL);
                 .
                 .
         }


6.2.3   Tuber´
             ıas, la forma f´cil de hacerlo
                            a
Si de todo lo visto anteriormente parece enredada la forma de crear y utilizar
tuber´ hay una alternativa:
      ıas,


  FUNCI´N DE LIBRER´A: popen();
       O           I

  PROTOTIPO: FILE *popen ( char *comando, char *tipo);
    RETORNA: si hay exito, nuevo "stream" de fichero
                    ´
             si no hay exito, NULL (por fallo en llamada pipe() o fork() ).
                       ´

  NOTAS: crea una tuber´a, y realiza las llamadas fork/exec
                       ı
         seg´n el "comando" pasado como argumento.
            u


    Esta funci´n est´ndar de la biblioteca crea una tuber´ semi-duplex lla-
               o     a                                     ıa
mando a pipe() internamente. Entonces adesdobla un proceso hijo, abre una
shell Bourne y ejecuta el argumento “command” en la shell. La direcci´n     o
del flujo de datos se determina por el segundo argumento, “type”. Puede
ser “r” o “w”, para “read” o “write”. ¡No pueden ser ambos!. Bajo Linux
la tuber´ se abrir´ seg´ n el modo especificado por el primer car´cter del
         ıa        a      u                                          a
argumento “type”. As´ si trata de pasar “rw”, s´lo lo abre en modo “read”.
                       ı,                         o
    Mientras esta funci´n de la biblioteca ejecuta realmente parte del trabajo
                       o
sucio por usted, hay un inconveniente substancial. Pierde parte del control
que ten´ con el uso de la llamada al sistema pipe(), y la manipulaci´n de
        ıa                                                               o
fork/exec por usted mismo. Sin embargo, como la shell de Bourne se usa
directamente, la expansi´n de metacaracteres de la shell (incluso plantillas)
                          o
est´ permitida dentro del argumento “comando”.
   a
    Las tuber´ que se crean con popen() se debe cerrar con pclose(). Por
              ıas
ahora, probablemente se habr´ dado cuenta de que popen/pclose comparten
                               a
un parecido llamativo con las funciones I/O stream de fichero normal fopen()
y fclose().
28     CAP´                  ´
          ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

     FUNCI´N DE LIBRER´A: pclose();
          O           I

     PROTOTIPO: int pclose( FILE *stream );
       RETORNA: el c´digo de retorno de la llamada wait4()
                    o
                -1 si el "stream" pasado no es v´lido, o la llamada wait4() falla
                                                a

     NOTAS: espera a que el proceso que escribe en la tuberia termine,
     y luego cierra el "stream".


    La funci´n pclose() ejecuta un wait4() en el proceso desdoblado por
             o
popen(). Cuando vuelve, destruye la tuber´ y el stream de fichero de salida.
                                          ıa
Una vez m´s, es sin´nimo de la funci´n fclose() para ficheros E/S normales
           a        o                o
de stream.
    Considere este ejemplo, que abre una tuber´ al comando sort, y ordena
                                              ıa
un array de cadena de caracteres.:

/*****************************************************************************
 Parte de la "Guia Linux de Programacion - Capitulo 6"
 (C)opyright 1994-1995, Scott Burkett
 *****************************************************************************
 MODULO: popen1.c
 *****************************************************************************/

#include <stdio.h>

#define MAXSTRS 5

int main(void)
{
        int cntr;
        FILE *pipe_fp;
        char *strings[MAXSTRS] = { "eco", "bravo", "alpha",
                                  "charlie", "delta"};

          /* Crea una tuberia de un sentido llamando a popen() */
          if (( pipe_fp = popen("sort", "w")) == NULL)
          {
                  perror("popen");
                  exit(1);
          }

          /* Bucle de proceso */
          for(cntr=0; cntr<MAXSTRS; cntr++) {
´
6.2. PIPES UNIX SEMI-DUPLEX                                            29

                  fputs(strings[cntr], pipe_fp);
                  fputc(’n’, pipe_fp);
         }

         /* Cierra la tuberia */
         pclose(pipe_fp);

         return(0);
}

   Como popen() usa la shell para hacer su enlace, ¡todas las expansiones
de caracteres y metacaracteres de la shell est´n disponibles para su uso!
                                              a
Adem´s, t´cnicas m´s avanzadas tales como redirecci´n, e incluso la salida
      a e          a                                o
por tuber´ se puede utilizar con popen(). Considere el siguiente ejemplo:
         ıa

         popen("ls ~scottb", "r");
         popen("sort > /tmp/foo", "w");
         popen("sort | uniq | more", "w");

   Considere este peque˜ o programa como otro ejemplo de popen(), que
                       n
abre dos tuber´ (una a la orden ls, el otro a sort):
              ıas


/*****************************************************************************
 Parte de la "Guia Linux de Programacion - Capitulo 6"
 (C)opyright 1994-1995, Scott Burkett
 *****************************************************************************
 MODULO: popen2.c
 *****************************************************************************/

#include <stdio.h>

int main(void)
{
        FILE *pipein_fp, *pipeout_fp;
        char readbuf[80];

         /* Crea una tuberia de un sentido llamando a popen() */
         if (( pipein_fp = popen("ls", "r")) == NULL)
         {
                 perror("popen");
                 exit(1);
         }
30   CAP´                  ´
        ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

        /* Crea una tuberia de un sentido llamando a popen() */
        if (( pipeout_fp = popen("sort", "w")) == NULL)
        {
                perror("popen");
                exit(1);
        }

        /* Bucle de proceso */
        while(fgets(readbuf, 80, pipein_fp))
                fputs(readbuf, pipeout_fp);

        /* Cierre de las tuberias */
        pclose(pipein_fp);
        pclose(pipeout_fp);

        return(0);
}

   Para nuestra demostraci´n final de popen(), creamos un programa
                           o
gen´rico que abre una tuber´ entre una orden pasada y un nombre de
   e                       ıa
fichero:


/*****************************************************************************
 Parte de la "Guia Linux de Programacion - Capitulo 6"
 (C)opyright 1994-1995, Scott Burkett
 *****************************************************************************
 MODULO: popen3.c
 *****************************************************************************/

#include <stdio.h>

int main(int argc, char *argv[])
{
        FILE *pipe_fp, *infile;
        char readbuf[80];

        if( argc != 3) {
                fprintf(stderr, "USO:    popen3 [comando] [archivo]n");
                exit(1);
        }

        /* Abrir el fichero de entrada */
        if (( infile = fopen(argv[2], "rt")) == NULL)
´
6.2. PIPES UNIX SEMI-DUPLEX                                              31

         {
                   perror("fopen");
                   exit(1);
         }

         /* Crear una tuberia de un sentido llamando a popen() */
         if (( pipe_fp = popen(argv[1], "w")) == NULL)
         {
                 perror("popen");
                 exit(1);
         }

         /* Bucle de proceso */
         do {
                 fgets(readbuf, 80, infile);
                 if(feof(infile)) break;

                 fputs(readbuf, pipe_fp);
         } while(!feof(infile));

         fclose(infile);
         pclose(pipe_fp);

         return(0);
}
    Pruebe este programa, con las llamadas siguientes:
         popen3   sort popen3.c
         popen3   cat popen3.c
         popen3   more popen3.c
         popen3   cat popen3.c | grep main

6.2.4   Operaciones at´micas con tuber´
                      o               ıas
Para que una operaci´n se considere “at´mica”, no se debe interrumpir de
                    o                  o
ninguna manera. Todo su funcionamiento ocurre de una vez. La norma
POSIX indica en /usr/include/posix1 lim.h que el tama˜ o m´ximo del
                                                          n    a
buffer para una operaci´n at´mica en una tuber´ es:
                      o    o                  ıa
         #define _POSIX_PIPE_BUF                512
    Hasta 512 bytes se pueden escribir o recuperar de una tuber´          ıa
at´micamente. Cualquier cosa que sobrepase este l´
  o                                              ımite se partir´. Bajo Li-
                                                                a
nux sin embargo, se define el l´
                              ımite at´mico operacional en “linux/limits.h”
                                      o
como:
32    CAP´                  ´
         ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

           #define PIPE_BUF              4096

    Como puede ver, Linux adapta el n´ mero m´
                                       u        ınimo de bytes requerido por
POSIX, y se le pueden agregar bastantes. La atomicidad del funcionamiento
de tuber´ se vuelve importante cuando implica m´s de un proceso (FIFOS).
         ıa                                        a
Por ejemplo, si el n´ mero de bytes escritos en una tuber´ excede el l´
                     u                                    ıa           ımite
at´mico para una simple operaci´n, y procesos m´ ltiples est´n escribiendo
  o                              o                  u         a
en la tuber´ los datos ser´n “intercalados” o “chunked”. En otras palabras,
            ıa,           a
un proceso insertar´ datos en la tuber´ entre la escritura de otro.
                    ıa                 ıa

6.2.5     Notas acerca de las tuber´ semi-d´ plex:
                                   ıas     u
     • Se pueden crear tuber´ de dos direcciones abriendo dos tuber´ y
                              ıas                                  ıas,
       reasignado los descriptores de fichero al proceso hijo.

     • La llamada a pipe() debe hacerse ANTES de la llamada a fork(), o los
       hijos no heredar´n los descriptores (igual que en popen()).
                       a

     • Con tuber´ semi -duplex, cualquier proceso conectado debe compar-
                  ıas
       tir el ancestro indicado. Como la tuber´ reside en el n´ cleo, cualquier
                                               ıa             u
       proceso que no sea ancestro del creador de la tuber´ no tiene forma de
                                                          ıa
       direccionarlo. Este no es el caso de las tuber´ con nombre (FIFOS).
                                                     ıas


6.3      Tuber´ con Nombre (FIFO - First In First
              ıas
         Out)
6.3.1     Conceptos b´sicos
                     a
Una tuber´ con nombre funciona como una tuber´ normal, pero tiene al-
          ıa                                 ıa
gunas diferencias notables.

     • Las tuber´ con nombre existen en el sistema de archivos como un
                 ıas
       archivo de dispositivo especial.

     • Los procesos de diferentes padres pueden compartir datos mediante
       una tuber´ con nombre.
                ıa

     • Cuando se han realizados todas las I/O por procesos compartidos, la
       tuber´ con nombre permanece en el sistema de archivos para un uso
            ıa
       posterior.

6.3.2     Creaci´n de una FIFO
                o
Hay varias formas de crear una tuber´ con nombre. Las dos primeras se
                                       ıa
pueden hacer directamente de la shell.
6.3. TUBER´
          IAS CON NOMBRE (FIFO - FIRST IN FIRST OUT)                    33

         mknod MIFIFO p
         mkfifo a=rw MIFIFO

   Los dos comandos anteriores realizan operaciones id´nticas, con una
                                                            e
excepci´n. El comando mkfifo proporciona una posibilidad de alterar los
        o
permisos del fichero FIFO directamente tras la creaci´n. Con mknod ser´
                                                       o                a
necesaria una llamada al comando chmod.
   Los ficheros FIFO se pueden identificar r´pidamente en un archivo f´
                                             a                      ısico
por el indicador ”p”que aparece en la lista del directorio.

         $ ls -l MIFIFO
         prw-r--r--   1 root          root               0 Dec 14 22:15 MIFIFO|

    Tambi´n hay que observar que la barra vertical (”s´
          e                                           ımbolo pipe”) est´
                                                                       a
situada inmediatamente detr´s del nombre de fichero. Otra gran raz´n para
                           a                                     o
usar Linux ¿eh?
    Para crear un FIFO en C, podemos hacer uso de la llamada del sistema
mknod():

  FUNCI´N DE LIBRER´A: mknod();
       O           I

  PROTOTIPO: int mknod( char *nombre, mode_t modo, dev_t disp);
    RETURNS: 0 si exito,
                  ´
             -1 si error: errno = EFAULT (nombre no v´lido)
                                                     a
                                  EACCES (permiso denegado)
                                  ENAMETOOLONG (nombre demasiado largo)
                                  ENOENT (nombre no v´lido)
                                                     a
                                  ENOTDIR (nombre no v´lido)
                                                       a
                                  (vea la p´gina mknod(3) para m´s informaci´n)
                                           a                    a           o

  NOTES: Crea un nodo del sistema de ficheros (fichero, dispositivo, o FIFO)

   Dejar´ una discusi´n m´s detallada de mknod() a la p´gina del manual,
         e           o   a                             a
pero lo podemos considerear un simple ejemplo de la creaci´n de un FIFO
                                                          o
en C:

                   mknod("/tmp/MIFIFO", S_IFIFO|0666, 0);

   En este caso el fichero “/tmp/MIFIFO” se crea como fichero FIFO. Los
permisos requeridos son “0666”, aunque se ven afectados por la configuraci´n
                                                                         o
de umask de la siguiente forma:

          umask_definitiva = permisos_solicitados & ~umask_inicial

   Un truco com´ n es usar la llamada del sisterma umask() para borrar
                u
temporalmente el valor de umask:
34   CAP´                  ´
        ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

                   umask(0);
                   mknod("/tmp/MIFIFO", S_IFIFO|0666, 0);

    Adem´s, el tercer argumento de mknod() se ignora salvo que estemos
         a
creando un archivo de dispositivo. En ese caso, se deber´ especificar los
                                                        ıa
n´ meros mayor y menor del fichero de dispositivo.
 u

6.3.3   Operaciones con FIFOs
Las operaciones E/S sobre un FIFOson esencialmente las mismas que para
las tuber´ normales, con una gran excepci´n. Se deber´ usar una llamada
          ıas                                o          ıa
              o    o
del sistema pen una funci´n de librer´ para abrir f´
                             o            ıa           ısicamente un canal
para la tuber´ Con las tuber´ semi-duplex, esto es innecesario, ya que la
               ıa.             ıas
tuber´ reside en el n´ cleo y no en un sistemade archivos f´
       ıa            u                                     ısico. En nuestro
ejemplo trataremos la tuber´ como un stream, abi´ndolo con fopen(), y
                              ıa                     e
cerr´ndolo con fclose().
     a
    Consideramos un proceso servidor simple:

/*****************************************************************************
 Parte de la "Guia Linux de Programacion - Capitulo 6"
 (C)opyright 1994-1995, Scott Burkett
 *****************************************************************************
 MODULO: fifoserver.c
 *****************************************************************************/

#include   <stdio.h>
#include   <stdlib.h>
#include   <sys/stat.h>
#include   <unistd.h>

#include <linux/stat.h>

#define FIFO_FILE            "MIFIFO"

int main(void)
{
        FILE *fp;
        char readbuf[80];

         /* Crea el FIFO si no existe */
         umask(0);
         mknod(FIFO_FILE, S_IFIFO|0666, 0);

         while(1)
6.3. TUBER´
          IAS CON NOMBRE (FIFO - FIRST IN FIRST OUT)                   35

         {
                  fp = fopen(FIFO_FILE, "r");
                  fgets(readbuf, 80, fp);
                  printf("Cadena recibida: %sn", readbuf);
                  fclose(fp);
         }

         return(0);
}

    Como un FIFO bloquea por defecto, ejecute el servidor en segundo plano
tras compilarlo:

         $ fifoserver&

   Discutiremos la acci´n de bloqueo de un FIFO en un momento. Primero
                       o
considrearemos el siguiente cliente simple enfrentado a nuestro servidor:


/*****************************************************************************
 Parte de la "Guia Linux de Programacion - Capitulo 6"
 (C)opyright 1994-1995, Scott Burkett
 *****************************************************************************
 MODULO: fifoclient.c
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>

#define FIFO_FILE           "MIFIFO"

int main(int argc, char *argv[])
{
        FILE *fp;

         if ( argc != 2 ) {
                 printf("USO: fifoclient [cadena]n");
                 exit(1);
         }

         if((fp = fopen(FIFO_FILE, "w")) == NULL) {
                 perror("fopen");
                 exit(1);
         }
36    CAP´                  ´
         ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX



         fputs(argv[1], fp);

         fclose(fp);
         return(0);
}

6.3.4   Acciones Bloqueantes en una FIFO
Normalmente, el bloqueo ocurre en un FIFO. En otro palabras, si se abre
el FIFO para lectura, el proceso esar´ ”bloqueado”hasta que cualquier otro
                                      a
proceso lo abra para escritura. Esta acci´n funciona al rev´s tambi´n. Si este
                                         o                 e       e
comportamiento no nos interesa, se puede usar la bandera O NONBLOCK
en la llamada a open() para desactivar la acci´n de bloqueo por defecto.
                                                o
    En el caso de nuestro servidor simple, lo hemos puesto en segundo plano,
y permito hacer su bloqueo all´ La alternativa estar´ saltar a otra consola
                                 ı.                  ıan
virtual y ejecutar el cliente, cambiando de un lado a otro para ver la acci´n
                                                                           o
resultante.

6.3.5   La Infame Se˜ al SIGPIPE
                    n
En una ultima nota, las tuber´ deber´ tener a un lector y un escritor.
        ´                       ıas     ıan
Si un proceso trata de escribir en una tuber´ que no tiene lector, el n´ cleo
                                            ıa                         u
enviar´ la se˜ al SIGPIPE. Esto es imperativo cuando en la tuber´ se ven
      a      n                                                     ıa
envueltos m´s dos procesos.
            a


6.4     IPC en Sistema V
6.4.1   Conceptos fundamentales
Con Unix Sistema V, AT&T introdujo tres nuevas formas de las facilidades
IPC (colas de mensajes, sem´foros y memoria compartida). Mientras que el
                           a
comit´ POSIX aun no ha completado su estadarizaci´n de estas facilidades,
     e                                             o
la mayor´ de las implementaciones soportan ´stas. Adem´s, Berkeley (BSD)
         ıa                                e            a
usa sockets como su forma primaria de IPC, m´s que los elementos del
                                                 a
Sistema V. Linux tiene la habilidad de usar ambas formas de IPC (BSD y
System V), aunque no se discutir´n los socket hasta el ultimo cap´
                                 a                     ´         ıtulo.
    La implementaci´n para Linux del IPC System V fue escrita por Krishna
                    o
Balasubramanian, en balasub@cis.ohio-state.edu.

Identificadores IPC
Cada objeto IPC tiene un unico identificador IPC asociado con ´l. Cuando
                         ´                                   e
decimos “objeto IPC”, hablamos de una simple cola de mensaje, sem´foro
                                                                   a
o segmento de memoria compartida. Se usa este identificador, dentro del
6.4. IPC EN SISTEMA V                                                     37

n´ cleo, para identificar de forma unica un objeto IPC. Por ejemplo, para
 u                                  ´
acceder un segmento particular memoria compartida, lo unico que requiere
                                                          ´
es el valor ID unico que se le ha asignado a ese segmento.
               ´
    La unicidad de un identificador es importante seg´ n el tipo de obje-
                                                        u
to en cuesti´n. Para ilustrar esto, supondremos un identificador num´rico
             o                                                      e
“12345”. Mientras no puede haber nunca dos colas de mensajes, con este
mismo identificador existe la posibilidad que existan una cola de mensajes
y un segmento de memoria compartida que poseen el mismo identificador
num´rico.
     e

Claves IPC
                                                                   ´
Para obtener un identificador unico, debe utilizarse una clave. Esta debe
                                 ´
ser conocida por ambos procesos cliente y servidor. Este es el primer paso
para construir el entorno cliente/servidor de una aplicaci´n.
                                                           o
    Cuando usted llama por tel´fono a alguien, debe conocer su n´mero.
                                  e                                    u
Adem´s, la compa˜´a telef´nica debe conocer c´mo dirigir su llamada al
      a             nı       o                   o
destino. Una vez que el receptor responde a su llamada, la conexi´n tiene
                                                                     o
lugar.
    En el caso de los mecanismos IPC de Sistema V, el “tel´fono” coinci-
                                                               e
de con el tipo de objeto usado. La “compa˜´ telef´nica” o el sistema de
                                             nıa     o
encaminado, se puede equiparar con la clave IPC.
    La clave puede ser el mismo valor cada vez, incluyendo su c´digo en
                                                                    o
la propia aplicaci´n. Esta es una desventaja pues la clave requerida puede
                  o
estar ya en usa. Por eso, la funci´n ftok() nos ser´ util para generar claves
                                   o               a´
no utilizadas para el cliente y el servidor.

  FUNCI´N DE LIBRER´A: ftok();
       O           I

  PROTOTIPO: key_t ftok ( char *nombre, char proj );
    RETORNA: nueva clave IPC si hay exito
                                    ´
             -1 si no hubo exito, dejando errno con el valor de la llamada stat()
                           ´

    La clave del valor devuelto de ftok () se genera por la combinaci´n del
                                                                      o
n´ mero del inodo y del n´ mero menor de dispositivo del archivo argumento,
 u                       u
                                                                     ´
con el car´cter identificador del proyecto del segundo argumento. Este no
          a
garantiza la unicidad, pero una aplicaci´n puede comprobar las colisiones y
                                        o
reintentar la generaci´n de la clave.
                      o

         key_t   miclave;
         miclave = ftok("/tmp/miaplic", ’a’);

    En el caso anterior el directorio /tmp/miaplic se combina con la letra
’a’.Otro ejemplo com´ n es usar el directorio actual:
                     u
38   CAP´                  ´
        ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

         key_t   miclave;
         mykey = ftok(".", ’a’);

    El algoritmo de la generaci´n de la clave usado est´ completamente a
                                o                          a
la discreci´n del programador de la aplicaci´n. Mientras que tome medi-
           o                                   o
das para prevenir ls condiciones cr´
                                   ıticas, bloqueos, etc, cualquier m´todo es
                                                                     e
viable. Para nuestros prop´sitos de demostraci´n, usaremos ftok(). Si supo-
                           o                     o
nemos que cada proceso cliente estar´ ejecut´ndose desde un unico directorio
                                     a       a                ´
“home”, las claves generadas deben bastar por nuestras necesidades.
    El valor clave, sin embargo, se obtiene, se usa una llamada al sistema
IPC para crear u obtener acceso a los objetos IPC.

Comando ipcs
El comando ipcs puede utilizarse para obtener el estado de todos los objetos
IPC Sistema V. La versi´n para Linux de esta utilidad tambi´n fue preparada
                       o                                   e
por Krishna Balasubramanian.

ipcs     -q:       Mostrar solo colas de mensajes
ipcs     -s:       Mostrar solo los sem´foros
                                       a
ipcs     -m:       Mostrar solo la memoria compartida
ipcs --help:       Otros argumentos

   Por defecto, se muestran las tres categor´
                                            ıas. Consid´rese el siguiente
                                                       e
ejemplo de salida del comando ipcs:


------ Shared Memory Segments --------
shmid     owner     perms     bytes              nattch      status

------ Semaphore Arrays --------
semid     owner     perms     nsems              status

------ Message Queues --------
msqid     owner     perms     used-bytes           messages
0         root      660       5                    1

   Aqu´ vemos una simple cola mensaje que tiene un identificador “ 0.” Es
        ı
propiedad del root, y tiene permisos en octal de 660, o -rw-rw--. Hay un
mensaje en la cola, y ese mensaje tiene un tama˜ o del total de 5 bytes.
                                               n
   Los comandos ipcs son una herramienta muy potente que proporciona
una leve introducci´n en los mecanismos de almacenamiento del n´ cleo para
                   o                                             u
objetos IPC. Apr´ndalo, uselo, reverencielo.
                 e        ´
6.4. IPC EN SISTEMA V                                                      39

El Comando ipcrm
Se puede usar el comando ipcrm para quitar un objeto IPC del n´ cleo. u
Mientras que los objetos IPC se pueden quitar mediante llamadas al sistema
en el c´digo del usuario (veremos c´mo en un momento),aparece a menudo
       o                           o
la necesidad, sobre todo en ambientes del desarrollo, de quitar objetos IPC
a mano. Su uso es simple:

ipcrm <msg | sem | shm>        <IPC ID>

    Simplemente especifique si el objeto a eliminar es una cola de mensaje (
em msg), un sem´foro (sem), o un segmento de memoria compartida (shm).
                 a
El identificador de IPC se puede obtenr mediante los comandos ipcs. Tiene
que especificar el tipo de objeto, como los identificadores son unicos entre
                                                               ´
los del mismo tipo (retome nuestra discusi´n anterior).
                                          o

6.4.2   Colas de Mensajes
Conceptos B´sicos
           a
Las colas de mensaje se pueden describir mejor como una lista enlazada
interior dentro del espacio de direccionamiento del n´ cleo.Los mensajes se
                                                       u
pueden enviar a la cola en orden y recuperarlos de la cola en varias maneras
diferentes. Cada cola de mensaje (por supuesto) est´ identificada de forma
                                                     a
unica por un identificador IPC.
´

Estructuras interna y de datos de usuario
La clave para comprender totalmente tales temas complejos como el IPC
Sistema V es familiarizarse con las distintas estrcturas de datos internas que
residen dentro de los confines del n´ cleo mismo.El acceso directo a algunas
                                    u
de estas estructuras es necesario incluso en las operacions m´s primitivas,
                                                                a
mientras otros residen a un nivel mucho m´s bajo.
                                             a

Buffer de Mensaje La primera estructura que veremos es la estructura
msgbuf. Esta particular estructura de datos puede ser interpretada como
una plantilla por datos del mensaje. Mientras que un programador puede
elegir si definir estructuras de este tipo, es imperativo que entiende que hay
realmente una estructura del tipo msgbuf. Se declara en linux/msg.h como
sigue:

/* buffer de mensaje para llamadas msgsnd y msgrcv */
struct msgbuf {
    long mtype;         /* tipo de mensaje */
    char mtext[1];      /* texto del mensaje */
};
40    CAP´                  ´
         ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX



     Hay dos miembros en la estructura msgbuf:

mtype
       El tipo de mensaje, representado por un n´ mero positivo. ¡Y debe ser
                                                u
       un n´ mero positivo!
            u

mtext
       Los datos del mensaje en s´ mismo.
                                 ı

    La habilidad asignarle a un mensaje dado un tipo, esencialmente le da la
capacidad de multiplexar mensajes en una cola sola. Por ejemplo, al proceso
cliente se puede asignar a un n´ mero m´gico, que se puede usar como el tipo
                               u        a
de mensaje para mensajes enviados desde un proceso servidor. El servidor
mismo podr´ usar algunos otros n´ meros, que los clientes podr´ usar para
             ıa                    u                           ıan
enviarle mensajes. Por otra parte, una aplicaci´n podr´ marcar mensajes
                                                 o       ıa
de error como tener un mensaje tipo 1, petici´n de mensajes podr´ ser
                                                o                    ıan
tipo 2, etc. Las posibilidades son interminables.
    En otra nota no se confunda por el nombre demasiado descriptivo asig-
nado al elemento dato del mensaje (mtext). Este campo no se restringe a
contener s´lo arrays de car´cteres, sino cualquier tipo e dato, en cualquier
           o                a
forma. El campo mismo es realmente arbitrario, ya que esta estructura es
redefinida por el programador de la aplicaci´n. Considere esta redefinici´n:
                                            o                            o


struct my_msgbuf {
        long    mtype;                 /* Tipo de mensaje */
        long    request_id;            /* Identificador de petici´n */
                                                                 o
        struct client info;            /* Estructura de informaci´n del cliente */
                                                                 o
};

    Aqu´ vemos el tipo de mensaje, como antes, pero el resto de la estructura
        ı
ha sido reemplazado por otros dos elementos, uno de los cuales es otra
            ´
estructura. Esta es la belleza de las colas de mensajes. El n´ cleo no hace
                                                               u
ninguna traducci´n de datos. Se puede enviar cualquier informaci´n.
                 o                                                  o
    Sin embargo, existe un l´
                            ımite interior del m´ximo tama˜ o de un mensaje
                                                a          n
dado. En Linux se define ´ste en linux/msg.h como sigue:
                          e


#define MSGMAX      4056    /* <= 4056 */      /* Tama~no maximo del mensaje (bytes) */


   El mensajes no puede ser mayor de 4,056 bytes en total, incluyendo el
miembro mtype, que tiene una longitud de 4 bytes (long).
6.4. IPC EN SISTEMA V                                                    41

Estructura msg del N´ cleo El n´ cleo guarda cada mensaje en la cola
                        u           u
dentro de la estructura msg. Se define en linux/msg.h como sigue:

/* one msg structure for each message */
struct msg {
    struct msg *msg_next;   /* siguiente mensaje de la cola */
    long msg_type;
    char *msg_spot;         /* direccion del texto del mensaje */
    short msg_ts;           /* tama~no del texto del mensaje */
};

msg next
     Es un puntero al siguiente mensaje de la cola. Se almacenan como
     ouna lista simple enlazada en el espacio de direcciones del n´ cleo.
                                                                  u

msg type
     ´
     Este es el tipo de mensaje, como asignado en la estructura msgbuf del
     usuario.

msg spot
     Un puntero al inicio del cuerpo del mensaje.

msg ts
     La longitud del texto del mensaje o del cuerpo.

Estructura msqid ds del n´ cleo Cada uno de los tres tipos de objetos
                              u
IPC tienen una estructura de datos interna que se mantiene por el n´ cleo.
                                                                       u
Para las colas de mensaje, es la estructura msqid ds. El n´ cleo crea, alma-
                                                          u
cena, y mantiene un caso de esta estructura por cada cola de mensaje hace
cola creada en el sistema. Se define en linux/msg.h de la siguiente forma:

/* una estructura msqid por cada cola         del sistema */
struct msqid_ds {
    struct ipc_perm msg_perm;
    struct msg *msg_first; /* primer          mensaje de la cola */
    struct msg *msg_last;   /* ultimo         mensaje */
    time_t msg_stime;       /* ultimo         instante de msgsnd */
    time_t msg_rtime;       /* ultimo         instante de msgrcv */
    time_t msg_ctime;       /* ultimo         instante cambio */
    struct wait_queue *wwait;
    struct wait_queue *rwait;
    ushort msg_cbytes;
    ushort msg_qnum;
42   CAP´                  ´
        ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

     ushort msg_qbytes;          /* numero maximo de bytes en cola */
     ushort msg_lspid;           /* pid del ultimo msgsnd */
     ushort msg_lrpid;           /* pid de la ultima recepcion */
};

    Aunque tendr´ raramente que usar la mayor parte de los miembros de es-
                  a
ta estructura, daremos una descripci´n breve de est´ para completar nuestra
                                    o              a
visi´n:
    o

msg perm
                                                                      ´
     Un caso de la estructura ipc perm, que se define en linux/ipc.h. Este
     recoge la informaci´n del permiso para la cola de mensaje, incluso los
                        o
     permisos del acceso, e informaci´n sobre el creador de la cola (uid,
                                      o
     etc).
msg first
     Enlace al primer mensaje de la cola (cabecera de la lista).

msg last
     Enlace al ultimo mensaje de la cola (cola de la lista).
               ´
msg stime
     Instante (time t) del ultimo mensaje que se envi´ a la cola.
                           ´                         o

msg rtime
     Instante del ultimo mensaje recuperado de la cola.
                  ´
msg ctime
     Instantedel ultimo cambio hecho a la cola. (hablaremos de esto m´s
                 ´                                                   a
     tarde).

wwait
     y
rwait
     Punteros a la cola de espera del n´ cleo. Se usan cuando una operaci´n
                                        u                                 o
     sobre una cola de mensajes estima que el proceso entra en el estado de
     dormido (es decir, la cola est´ llena y el porceso espera una apertura).
                                   a
msg cbytes
     N´ mero total number de bytes que hay en la cola (suma de los tama˜ os
      u                                                                n
     de todos los mensajes).

msg qnum
     N´ mero de mansajes actual en la cola.
      u
6.4. IPC EN SISTEMA V                                                    43

msg qbytes
     M´ximo n´ mero de bytes en la cola.
      a      u

msg lspid
     El PID del proceso que env´ el ultimo mensaje.
                               ıa ´

msg lrpid
     El PID del proceso que recupera el ultimo mensaje.
                                        ´

Estructura ipc perm del n´ cleo El n´ cleo guarda informaci´n de per-
                              u            u                       o
misos para objetos IPC en una estructura de tipo ipc perm. Por ejemplo,
en la estructura interna para una cola de mensaje descrita antes, el miembro
de msg perm es de este tipo. Se declara en linux/ipc.h como sigue:


struct ipc_perm
{
  key_t key;
  ushort uid;      /* euid y egid del propietario */
  ushort gid;
  ushort cuid;     /* euid y egid del creador */
  ushort cgid;
  ushort mode;     /* modos de acceso, veanse despues los valores */
  ushort seq;      /* numero de secuencia del slot */
};

    Todo lo anterior es bastante autoexplicativo. Guardado junto con la
clave IPC del objeto hay informaci´n sobre el creador y due˜ o del obje-
                                    o                        n
to (pueden ser diferentes).Los modos del acceso octal como un unsigned
short. Finalmente, la secuencia del slot se guarda al final. Cada vez qye
un objeto IPC se cierra mediante una llamada al sistema llama (destruye),
este valor se incrementa por el m´ximo n´ mera de objetos IPC que pueden
                                 a       u
residir en un sistema. ¿Tendr´ que usar este valor? No.
                              a
    NOTA:Hay una excelente exposici´n de este tema, y los asuntos de
                                       o
seguridad relacionados, en el libro UNIX Network Programming, de
Richard Stevens (p´gina 125).
                    a

LLAMADA AL SISTEMA: msgget()
Para crear una nueva cola de mensajes, o acceder a una existente, usaremos
la llamada al sistema msgget().

  LLAMADA AL SISTEMA: msgget();
44     CAP´                  ´
          ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX

     PROTOTIPO: int msgget ( key_t clave, int msgflg );
       RETORNA: Si hay exito, identificador de la cola de mensajes
                       ´
                -1 si error: errno = EACCESS (permiso denegado)
                                     EEXIST (No puede crearse la cola pues ya exist
                                     EIDRM (La cola esta marcada para borrarse)
                                     ENOENT (La cola no existe)
                                     ENOMEM (No hay memoria para crear la cola)
                                     ENOSPC (Se ha superado el limite de colas)
     NOTAS:

    El primer argumento de msgget() es el valor clave (en nuestro caso
devuelto por una llamada a ftok(). Este valor clave se compara entonces
con los valores clave que existen dentro del n´ cleo de otras colas de mensaje.
                                              u
En ese punto las operaciones de apertura o acceso depende de los contenidos
del argumento msgflg.

IPC CREAT
       Crea la cola si aun no existe en el n´ cleo.
                                            u

IPC EXCL
       Cuando se usa con IPC CREAT, falla si la cola ya existe.

    Si usamos solo IPC CREAT, msgget() retornar´ el identificador de una
                                                   a
cola nueva, o bien el de la existente con la misma clave. Si usamos adem´s a
IPC EXCL, la llamada crear´ una nueva cola o fallar´ si la cola con esa clave
                             a                      a
ya exist´ La opci´n IPC EXCL es poco util si no se usa combinada con
        ıa.          o                      ´
IPC CREAT.
    Es posible incluir en la m´scara un modo opcional octal, pues cada objeto
                               a
IPC tiene un esquema de permisos de acceso similar a cualquier archivo del
sistema Unix.
    Creamos una funci´n de envoltura r´pida para abriro crear una cola de
                        o                a
mensaje:

int abrir_cola( key_t keyval )
{
        int     qid;

           if((qid = msgget( keyval, IPC_CREAT | 0660 )) == -1)
           {
                   return(-1);
           }

           return(qid);
}
6.4. IPC EN SISTEMA V                                                     45



    N´tese el uso del modo de permisos 0660. Esta peque˜ a funci´n retor-
     o                                                     n        o
nar´, bien un identificador entero de la cola de mensajes, o -1 si hubo error.
   a
El valor de la clave (keyval) debe ser el unico argumento de la llamada a la
                                          ´
funci´n.
     o

LLAMADA AL SISTEMA: msgsnd()
Una vez que tenemos el identificador de la cola, podemos empezar a realizar
operaciones sobre ella. Para entregar un mensaje a una cola, use la llamada
al sistema msgsndl:

  LLAMADA AL SISTEMA: msgsnd();

  PROTOTIPO: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg );
    RETORNA: 0 si exito
                  ´
             -1 si error: errno = EAGAIN (la cola est´ llena, y se us´ IPC_NOWAIT).
                                                     a               o
                                  EACCES (permiso denegado, no se puede escribir)
                                  EFAULT (Direcci´n de memoria de msgp inv´lida)
                                                 o                        a
                                  EIDRM (La cola de mensajes fue borrada)
                                  EINTR (Se recibi´ una se~al mientras se esperaba para
                                                   o       n
                                  EINVAL (Identificador de cola inv´lido, tipo
                                                                   a
                                          no positivo o tama~o de mensaje inv´lido)
                                                             n               a
                                  ENOMEM (No hay memoria suficiente para copiar el buffe
  NOTAS:

    El primer argumento de msgsnd es nuestro identificador de la cola, de-
vuelto por un llamada previa a msgget. El segundo argumento, msgp, es un
puntero a nuestro buffer redeclarado y cargado. El argumento msgsz contie-
ne el tama˜ o del mensaje en bytes, excluye la longitud del tipo de mensaje
           n
(4 byte).
    El argumento msgflg se puede poner a cero (ignorado), o:

IPC NOWAIT
     Si la cola del mensaje est´ llena, entonces no se escribe en la cola
                                a
     el mensaje, y se le devuelve el control la proceso llamador. Si no
     se especifica, entonces el proceso llamador se suspender´ (bloqueado)
                                                            a
     hasta que se puede escribir el mensaje.

   Creamos otra funci´n de la envoltura por enviar mensajes:
                     o

int enviar_msj( int qid, struct mymsgbuf *qbuf )
{
        int     resultado, longitud;
46   CAP´                  ´
        ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX



         /* La longitud es esencialmente el tama~no de la estructura menos sizeof
         longitud = sizeof(struct mymsgbuf) - sizeof(long);

         if((resultado = msgsnd( qid, qbuf, length, 0)) == -1)
         {
                 return(-1);
         }

         return(resultado);
}

    Esta peque˜ a funci´n intenta enviar un mensaje almacenado en la direc-
              n        o
ci´n pasada (qbuf) a la cola de mensajes identificada por el n´ mero pasado
  o                                                          u
en el argumento qid. Aqu´ tenemos un programa de ejemplo que utiliza las
                           ı
dos funciones que hemos desarrollado aqu´ ı:

#include   <stdio.h>
#include   <stdlib.h>
#include   <linux/ipc.h>
#include   <linux/msg.h>

main()
{
         int    qid;
         key_t msgkey;
         struct mymsgbuf    {
                 long       mtype;             /* Tipo de mensaje */
                 int        request;           /* Numero de trabajo */
                 double     salary;            /* Salario del empleado */
         } msg;

         /* Generamos nuestra clave IPC */
         msgkey = ftok(".", ’m’);

         /* Abrir/crear la cola */
         if(( qid = abrir_cola( msgkey)) == -1) {
                 perror("abrir_cola");
                 exit(1);
         }

         /* Preparar mensajes con datos arbitrarios */
         msg.mtype   = 1;        /* !El mensaje debe ser numero positivo! */
         msg.request = 1;        /* Dato numero 1 */
6.4. IPC EN SISTEMA V                                                    47

          msg.salary    = 1000.00;    /* Dato numero 2 (!mi salario anual!) */

          /* !Bombear mensaje! */
          if((enviar_msj( qid, &msg )) == -1) {
                  perror("enviar_msj");
                  exit(1);
          }
}

    Tras crear/abrir la cola de mensajes, pasamos a preparar el buffer del
mensaje con datos de prueba (note la falta de datos de tipo car´cter para
                                                                  a
ilustrar nuestro punto sobre env´o de informaci´n binaria). Una simple
                                  ı             o
llamada a enviar msj env´ nuestro mensaje a la cola.
                           ıa
    Ahora que tenemos un mensaje en la cola, probemos en comando ipcs
para comprobar el estado de ´sta. Ahora continuaremos con la discusi´n
                                e                                         o
para ver c´mo leer informaci´n del mensaje. Para ello, se utiliza la llamada
          o                   o
al sistema msgrcv():

    LLAMADA AL SISTEMA: msgrcv();
    PROTOTIPO: int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msg
      RETURNS: N´mero de bytes copiados en la cola de mensajes
                u
               -1 si error: errno = E2BIG (La longitud del mensaje es mayor que msgsz)
                                    EACCES (No hay permiso de lectura)
                                    EFAULT (La direcci´n del buffer msgp es incorrecta)
                                                      o
                                    EIDRM (La cola fue eliminada durante la lectura)
                                    EINTR (Interrumpido por llegada de se~al)
                                                                          n
                                    EINVAL (msgqid inv´lida, o msgsz menor que 0)
                                                      a
                                    ENOMSG (IPC_NOWAIT incluido, y no hay mensajeen la
                                            cola disponible para leer)
    NOTAS:

    Obviamente, el primer argumento se usa para especificar la cola utiliza-
da durante el proceso de recuperaci´n del mensaje (se deber´ haber sido
                                    o                         ıa
devuelto por una llamada anterior a msgget). El segundo argumento (msgp)
representa la direcci´n de una variable buffer de mensaje para guardar el
                     o
mensaje recuperado. El tercer argumento, (msgsz), representa el tama˜ o n
de la estructura del buffer del mensaje, excluye la longitud del miembro de
mtype. Una vez m´s, se puede calcular ´ste f´cilmente como:
                   a                   e     a

msgsz = sizeof(struct mymsgbuf) - sizeof(long);

    El cuarto argumento (mtype) especifica el tipo de mensaje a recuperar
de la cola. El n´ cleo buscar´ la cola por el ultimo mensaje que cuadra con
                 u           a                ´
el tipo, y le devolver´ a una copia de ´l en la direcci´n apuntada a por el
                      a                 e              o
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11
Gulp 0.11

Más contenido relacionado

La actualidad más candente

Tutorial de maxima
Tutorial de maximaTutorial de maxima
Tutorial de maximalichowlin
 
Introduccion al lenguaje c
Introduccion al lenguaje cIntroduccion al lenguaje c
Introduccion al lenguaje cChucho E. Peña
 
Muestreo y reconstruccion UPTC 2011
Muestreo y reconstruccion UPTC 2011Muestreo y reconstruccion UPTC 2011
Muestreo y reconstruccion UPTC 2011buxtehude04
 
Practica5 bash prog-intro-como
Practica5 bash prog-intro-comoPractica5 bash prog-intro-como
Practica5 bash prog-intro-comoAngie Hernandez
 
Informatica -fundamentos_sistemas_operativos_linux_window
Informatica  -fundamentos_sistemas_operativos_linux_windowInformatica  -fundamentos_sistemas_operativos_linux_window
Informatica -fundamentos_sistemas_operativos_linux_windowJohn Lopez
 
1246876145manualprogramacióNcastellano 050906
1246876145manualprogramacióNcastellano 0509061246876145manualprogramacióNcastellano 050906
1246876145manualprogramacióNcastellano 050906Alfmaro
 
Alejandro tfm
Alejandro tfmAlejandro tfm
Alejandro tfmmpaljacar
 
Guia rapida
Guia rapidaGuia rapida
Guia rapidacamforma
 
Unlock manual sony
Unlock manual sonyUnlock manual sony
Unlock manual sonyamatcar
 
Eterboard
EterboardEterboard
EterboardMexalit
 
Vba excel numericos
Vba excel numericosVba excel numericos
Vba excel numericosJOHN BONILLA
 

La actualidad más candente (18)

Rarepaso
RarepasoRarepaso
Rarepaso
 
Catalogo
CatalogoCatalogo
Catalogo
 
Tutorial de maxima
Tutorial de maximaTutorial de maxima
Tutorial de maxima
 
Introduccion al lenguaje c
Introduccion al lenguaje cIntroduccion al lenguaje c
Introduccion al lenguaje c
 
Muestreo y reconstruccion UPTC 2011
Muestreo y reconstruccion UPTC 2011Muestreo y reconstruccion UPTC 2011
Muestreo y reconstruccion UPTC 2011
 
Curso de html y phpnuke
Curso de html y phpnukeCurso de html y phpnuke
Curso de html y phpnuke
 
Practica5 bash prog-intro-como
Practica5 bash prog-intro-comoPractica5 bash prog-intro-como
Practica5 bash prog-intro-como
 
Informatica -fundamentos_sistemas_operativos_linux_window
Informatica  -fundamentos_sistemas_operativos_linux_windowInformatica  -fundamentos_sistemas_operativos_linux_window
Informatica -fundamentos_sistemas_operativos_linux_window
 
1246876145manualprogramacióNcastellano 050906
1246876145manualprogramacióNcastellano 0509061246876145manualprogramacióNcastellano 050906
1246876145manualprogramacióNcastellano 050906
 
Alejandro tfm
Alejandro tfmAlejandro tfm
Alejandro tfm
 
Guia rapida
Guia rapidaGuia rapida
Guia rapida
 
Unlock manual sony
Unlock manual sonyUnlock manual sony
Unlock manual sony
 
Libro ed lat
Libro ed latLibro ed lat
Libro ed lat
 
Eterboard
EterboardEterboard
Eterboard
 
Catalogo12
Catalogo12Catalogo12
Catalogo12
 
Abraham linux
Abraham linuxAbraham linux
Abraham linux
 
Calculo
CalculoCalculo
Calculo
 
Vba excel numericos
Vba excel numericosVba excel numericos
Vba excel numericos
 

Destacado

Destacado (6)

Programacion bajo linux
Programacion bajo linuxProgramacion bajo linux
Programacion bajo linux
 
Capacitación Mikrotik desde Cero - práctica
Capacitación Mikrotik desde Cero - prácticaCapacitación Mikrotik desde Cero - práctica
Capacitación Mikrotik desde Cero - práctica
 
Capacitación Mikrotik desde Cero
Capacitación Mikrotik desde CeroCapacitación Mikrotik desde Cero
Capacitación Mikrotik desde Cero
 
Elastix manual
Elastix manualElastix manual
Elastix manual
 
Mikrotik ultimo manual
Mikrotik ultimo manualMikrotik ultimo manual
Mikrotik ultimo manual
 
Inter Process Communication
Inter Process CommunicationInter Process Communication
Inter Process Communication
 

Similar a Gulp 0.11

Dialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdf
Dialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdfDialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdf
Dialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdfClaudia Naveda
 
Libro programación-en-c++
Libro programación-en-c++Libro programación-en-c++
Libro programación-en-c++Andres Escobar
 
Dentro nucleo linux
Dentro nucleo linuxDentro nucleo linux
Dentro nucleo linux1 2d
 
Libro javacontapa
Libro javacontapaLibro javacontapa
Libro javacontapaRobert Wolf
 
Libro javacontapa
Libro javacontapaLibro javacontapa
Libro javacontapaTabu Carlos
 
pensar_en_cpp-vol1.pdf
pensar_en_cpp-vol1.pdfpensar_en_cpp-vol1.pdf
pensar_en_cpp-vol1.pdfmacario17
 
Desarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-javaDesarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-javaFreddy Quina
 
Desarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-javaDesarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-javaVictor Basurto Alonso
 
Programacion en Phyton desde ce..........................ro
Programacion en Phyton desde ce..........................roProgramacion en Phyton desde ce..........................ro
Programacion en Phyton desde ce..........................roMa Florencia Ferrari
 
Introduccion a los Sistemas Digitales
Introduccion a los Sistemas DigitalesIntroduccion a los Sistemas Digitales
Introduccion a los Sistemas Digitalesgiov gmb
 
Algoritmos programacion-python
Algoritmos programacion-pythonAlgoritmos programacion-python
Algoritmos programacion-pythonLUIS COAQUIRA
 
MANUAL DE LENGUAJE C
MANUAL DE LENGUAJE CMANUAL DE LENGUAJE C
MANUAL DE LENGUAJE Cclaudiocj7
 
Tutorial xhtml y css
Tutorial xhtml y cssTutorial xhtml y css
Tutorial xhtml y cssiConstruye
 

Similar a Gulp 0.11 (20)

Intro2
Intro2Intro2
Intro2
 
Dialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdf
Dialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdfDialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdf
Dialnet-MemoriaDinamicaEnElLenguajeDeProgramacionC-652144.pdf
 
Libro programación-en-c++
Libro programación-en-c++Libro programación-en-c++
Libro programación-en-c++
 
Manual LyX: Con "L" de LaTeX
Manual LyX: Con "L" de LaTeXManual LyX: Con "L" de LaTeX
Manual LyX: Con "L" de LaTeX
 
Dentro nucleo linux
Dentro nucleo linuxDentro nucleo linux
Dentro nucleo linux
 
Libro javacontapa
Libro javacontapaLibro javacontapa
Libro javacontapa
 
Libro javacontapa
Libro javacontapaLibro javacontapa
Libro javacontapa
 
Algoritmos
AlgoritmosAlgoritmos
Algoritmos
 
pensar_en_cpp-vol1.pdf
pensar_en_cpp-vol1.pdfpensar_en_cpp-vol1.pdf
pensar_en_cpp-vol1.pdf
 
Desarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-javaDesarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-java
 
Desarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-javaDesarrollo proyectos-informaticos-con-java
Desarrollo proyectos-informaticos-con-java
 
Programacion en Phyton desde ce..........................ro
Programacion en Phyton desde ce..........................roProgramacion en Phyton desde ce..........................ro
Programacion en Phyton desde ce..........................ro
 
Guia vim
Guia vimGuia vim
Guia vim
 
Tutorial c18
Tutorial c18Tutorial c18
Tutorial c18
 
Introduccion a los Sistemas Digitales
Introduccion a los Sistemas DigitalesIntroduccion a los Sistemas Digitales
Introduccion a los Sistemas Digitales
 
Algoritmos programacion-python
Algoritmos programacion-pythonAlgoritmos programacion-python
Algoritmos programacion-python
 
Vba excel mnumericos1
Vba excel mnumericos1Vba excel mnumericos1
Vba excel mnumericos1
 
Vba excel mnumericos
Vba excel mnumericosVba excel mnumericos
Vba excel mnumericos
 
MANUAL DE LENGUAJE C
MANUAL DE LENGUAJE CMANUAL DE LENGUAJE C
MANUAL DE LENGUAJE C
 
Tutorial xhtml y css
Tutorial xhtml y cssTutorial xhtml y css
Tutorial xhtml y css
 

Más de 1 2d

Notas clase
Notas claseNotas clase
Notas clase1 2d
 
Notas clase java ii
Notas clase java iiNotas clase java ii
Notas clase java ii1 2d
 
J2me
J2meJ2me
J2me1 2d
 
6. control de acceso
6. control de acceso6. control de acceso
6. control de acceso1 2d
 
5. administracioìn de claves y certificados
5. administracioìn de claves y certificados5. administracioìn de claves y certificados
5. administracioìn de claves y certificados1 2d
 
4. certificados digitales
4. certificados digitales4. certificados digitales
4. certificados digitales1 2d
 
3. boletines de mensajes y firmas digitales
3. boletines de mensajes y firmas digitales3. boletines de mensajes y firmas digitales
3. boletines de mensajes y firmas digitales1 2d
 
2. criptografiìa con java
2. criptografiìa con java2. criptografiìa con java
2. criptografiìa con java1 2d
 
1. introduccioìn a la seguridad
1. introduccioìn a la seguridad1. introduccioìn a la seguridad
1. introduccioìn a la seguridad1 2d
 
1046 pdfsam opos informatica
1046 pdfsam opos informatica1046 pdfsam opos informatica
1046 pdfsam opos informatica1 2d
 
1203 pdfsam opos informatica
1203 pdfsam opos informatica1203 pdfsam opos informatica
1203 pdfsam opos informatica1 2d
 
878 pdfsam opos informatica
878 pdfsam opos informatica878 pdfsam opos informatica
878 pdfsam opos informatica1 2d
 
516 pdfsam opos informatica
516 pdfsam opos informatica516 pdfsam opos informatica
516 pdfsam opos informatica1 2d
 
1704 pdfsam opos informatica
1704 pdfsam opos informatica1704 pdfsam opos informatica
1704 pdfsam opos informatica1 2d
 
1893 pdfsam opos informatica
1893 pdfsam opos informatica1893 pdfsam opos informatica
1893 pdfsam opos informatica1 2d
 
516 pdfsam opos informatica
516 pdfsam opos informatica516 pdfsam opos informatica
516 pdfsam opos informatica1 2d
 
706 pdfsam opos informatica
706 pdfsam opos informatica706 pdfsam opos informatica
706 pdfsam opos informatica1 2d
 
330 pdfsam opos informatica
330 pdfsam opos informatica330 pdfsam opos informatica
330 pdfsam opos informatica1 2d
 
1 pdfsam opos informatica
1 pdfsam opos informatica1 pdfsam opos informatica
1 pdfsam opos informatica1 2d
 
1379 pdfsam opos informatica
1379 pdfsam opos informatica1379 pdfsam opos informatica
1379 pdfsam opos informatica1 2d
 

Más de 1 2d (20)

Notas clase
Notas claseNotas clase
Notas clase
 
Notas clase java ii
Notas clase java iiNotas clase java ii
Notas clase java ii
 
J2me
J2meJ2me
J2me
 
6. control de acceso
6. control de acceso6. control de acceso
6. control de acceso
 
5. administracioìn de claves y certificados
5. administracioìn de claves y certificados5. administracioìn de claves y certificados
5. administracioìn de claves y certificados
 
4. certificados digitales
4. certificados digitales4. certificados digitales
4. certificados digitales
 
3. boletines de mensajes y firmas digitales
3. boletines de mensajes y firmas digitales3. boletines de mensajes y firmas digitales
3. boletines de mensajes y firmas digitales
 
2. criptografiìa con java
2. criptografiìa con java2. criptografiìa con java
2. criptografiìa con java
 
1. introduccioìn a la seguridad
1. introduccioìn a la seguridad1. introduccioìn a la seguridad
1. introduccioìn a la seguridad
 
1046 pdfsam opos informatica
1046 pdfsam opos informatica1046 pdfsam opos informatica
1046 pdfsam opos informatica
 
1203 pdfsam opos informatica
1203 pdfsam opos informatica1203 pdfsam opos informatica
1203 pdfsam opos informatica
 
878 pdfsam opos informatica
878 pdfsam opos informatica878 pdfsam opos informatica
878 pdfsam opos informatica
 
516 pdfsam opos informatica
516 pdfsam opos informatica516 pdfsam opos informatica
516 pdfsam opos informatica
 
1704 pdfsam opos informatica
1704 pdfsam opos informatica1704 pdfsam opos informatica
1704 pdfsam opos informatica
 
1893 pdfsam opos informatica
1893 pdfsam opos informatica1893 pdfsam opos informatica
1893 pdfsam opos informatica
 
516 pdfsam opos informatica
516 pdfsam opos informatica516 pdfsam opos informatica
516 pdfsam opos informatica
 
706 pdfsam opos informatica
706 pdfsam opos informatica706 pdfsam opos informatica
706 pdfsam opos informatica
 
330 pdfsam opos informatica
330 pdfsam opos informatica330 pdfsam opos informatica
330 pdfsam opos informatica
 
1 pdfsam opos informatica
1 pdfsam opos informatica1 pdfsam opos informatica
1 pdfsam opos informatica
 
1379 pdfsam opos informatica
1379 pdfsam opos informatica1379 pdfsam opos informatica
1379 pdfsam opos informatica
 

Último

plande accion dl aula de innovación pedagogica 2024.pdf
plande accion dl aula de innovación pedagogica 2024.pdfplande accion dl aula de innovación pedagogica 2024.pdf
plande accion dl aula de innovación pedagogica 2024.pdfenelcielosiempre
 
Curso = Metodos Tecnicas y Modelos de Enseñanza.pdf
Curso = Metodos Tecnicas y Modelos de Enseñanza.pdfCurso = Metodos Tecnicas y Modelos de Enseñanza.pdf
Curso = Metodos Tecnicas y Modelos de Enseñanza.pdfFrancisco158360
 
plan de capacitacion docente AIP 2024 clllll.pdf
plan de capacitacion docente  AIP 2024          clllll.pdfplan de capacitacion docente  AIP 2024          clllll.pdf
plan de capacitacion docente AIP 2024 clllll.pdfenelcielosiempre
 
origen y desarrollo del ensayo literario
origen y desarrollo del ensayo literarioorigen y desarrollo del ensayo literario
origen y desarrollo del ensayo literarioELIASAURELIOCHAVEZCA1
 
Cuaderno de trabajo Matemática 3 tercer grado.pdf
Cuaderno de trabajo Matemática 3 tercer grado.pdfCuaderno de trabajo Matemática 3 tercer grado.pdf
Cuaderno de trabajo Matemática 3 tercer grado.pdfNancyLoaa
 
Criterios ESG: fundamentos, aplicaciones y beneficios
Criterios ESG: fundamentos, aplicaciones y beneficiosCriterios ESG: fundamentos, aplicaciones y beneficios
Criterios ESG: fundamentos, aplicaciones y beneficiosJonathanCovena1
 
Valoración Crítica de EEEM Feco2023 FFUCV
Valoración Crítica de EEEM Feco2023 FFUCVValoración Crítica de EEEM Feco2023 FFUCV
Valoración Crítica de EEEM Feco2023 FFUCVGiustinoAdesso1
 
OCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VS
OCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VSOCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VS
OCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VSYadi Campos
 
Dinámica florecillas a María en el mes d
Dinámica florecillas a María en el mes dDinámica florecillas a María en el mes d
Dinámica florecillas a María en el mes dstEphaniiie
 
AFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA II
AFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA IIAFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA II
AFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA IIIsauraImbrondone
 
La triple Naturaleza del Hombre estudio.
La triple Naturaleza del Hombre estudio.La triple Naturaleza del Hombre estudio.
La triple Naturaleza del Hombre estudio.amayarogel
 
Ley 21.545 - Circular Nº 586.pdf circular
Ley 21.545 - Circular Nº 586.pdf circularLey 21.545 - Circular Nº 586.pdf circular
Ley 21.545 - Circular Nº 586.pdf circularMooPandrea
 
FORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURA
FORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURAFORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURA
FORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURAEl Fortí
 
CALENDARIZACION DE MAYO / RESPONSABILIDAD
CALENDARIZACION DE MAYO / RESPONSABILIDADCALENDARIZACION DE MAYO / RESPONSABILIDAD
CALENDARIZACION DE MAYO / RESPONSABILIDADauxsoporte
 
SEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptx
SEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptxSEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptx
SEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptxYadi Campos
 
Imperialismo informal en Europa y el imperio
Imperialismo informal en Europa y el imperioImperialismo informal en Europa y el imperio
Imperialismo informal en Europa y el imperiomiralbaipiales2016
 
TIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptx
TIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptxTIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptx
TIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptxlclcarmen
 
Sesión de aprendizaje Planifica Textos argumentativo.docx
Sesión de aprendizaje Planifica Textos argumentativo.docxSesión de aprendizaje Planifica Textos argumentativo.docx
Sesión de aprendizaje Planifica Textos argumentativo.docxMaritzaRetamozoVera
 

Último (20)

plande accion dl aula de innovación pedagogica 2024.pdf
plande accion dl aula de innovación pedagogica 2024.pdfplande accion dl aula de innovación pedagogica 2024.pdf
plande accion dl aula de innovación pedagogica 2024.pdf
 
Curso = Metodos Tecnicas y Modelos de Enseñanza.pdf
Curso = Metodos Tecnicas y Modelos de Enseñanza.pdfCurso = Metodos Tecnicas y Modelos de Enseñanza.pdf
Curso = Metodos Tecnicas y Modelos de Enseñanza.pdf
 
plan de capacitacion docente AIP 2024 clllll.pdf
plan de capacitacion docente  AIP 2024          clllll.pdfplan de capacitacion docente  AIP 2024          clllll.pdf
plan de capacitacion docente AIP 2024 clllll.pdf
 
origen y desarrollo del ensayo literario
origen y desarrollo del ensayo literarioorigen y desarrollo del ensayo literario
origen y desarrollo del ensayo literario
 
Cuaderno de trabajo Matemática 3 tercer grado.pdf
Cuaderno de trabajo Matemática 3 tercer grado.pdfCuaderno de trabajo Matemática 3 tercer grado.pdf
Cuaderno de trabajo Matemática 3 tercer grado.pdf
 
Criterios ESG: fundamentos, aplicaciones y beneficios
Criterios ESG: fundamentos, aplicaciones y beneficiosCriterios ESG: fundamentos, aplicaciones y beneficios
Criterios ESG: fundamentos, aplicaciones y beneficios
 
Valoración Crítica de EEEM Feco2023 FFUCV
Valoración Crítica de EEEM Feco2023 FFUCVValoración Crítica de EEEM Feco2023 FFUCV
Valoración Crítica de EEEM Feco2023 FFUCV
 
OCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VS
OCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VSOCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VS
OCTAVO SEGUNDO PERIODO. EMPRENDIEMIENTO VS
 
Dinámica florecillas a María en el mes d
Dinámica florecillas a María en el mes dDinámica florecillas a María en el mes d
Dinámica florecillas a María en el mes d
 
AFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA II
AFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA IIAFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA II
AFICHE EL MANIERISMO HISTORIA DE LA ARQUITECTURA II
 
La triple Naturaleza del Hombre estudio.
La triple Naturaleza del Hombre estudio.La triple Naturaleza del Hombre estudio.
La triple Naturaleza del Hombre estudio.
 
Ley 21.545 - Circular Nº 586.pdf circular
Ley 21.545 - Circular Nº 586.pdf circularLey 21.545 - Circular Nº 586.pdf circular
Ley 21.545 - Circular Nº 586.pdf circular
 
FORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURA
FORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURAFORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURA
FORTI-MAYO 2024.pdf.CIENCIA,EDUCACION,CULTURA
 
CALENDARIZACION DE MAYO / RESPONSABILIDAD
CALENDARIZACION DE MAYO / RESPONSABILIDADCALENDARIZACION DE MAYO / RESPONSABILIDAD
CALENDARIZACION DE MAYO / RESPONSABILIDAD
 
Tema 8.- PROTECCION DE LOS SISTEMAS DE INFORMACIÓN.pdf
Tema 8.- PROTECCION DE LOS SISTEMAS DE INFORMACIÓN.pdfTema 8.- PROTECCION DE LOS SISTEMAS DE INFORMACIÓN.pdf
Tema 8.- PROTECCION DE LOS SISTEMAS DE INFORMACIÓN.pdf
 
SEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptx
SEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptxSEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptx
SEXTO SEGUNDO PERIODO EMPRENDIMIENTO.pptx
 
Imperialismo informal en Europa y el imperio
Imperialismo informal en Europa y el imperioImperialismo informal en Europa y el imperio
Imperialismo informal en Europa y el imperio
 
TIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptx
TIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptxTIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptx
TIPOLOGÍA TEXTUAL- EXPOSICIÓN Y ARGUMENTACIÓN.pptx
 
Presentacion Metodología de Enseñanza Multigrado
Presentacion Metodología de Enseñanza MultigradoPresentacion Metodología de Enseñanza Multigrado
Presentacion Metodología de Enseñanza Multigrado
 
Sesión de aprendizaje Planifica Textos argumentativo.docx
Sesión de aprendizaje Planifica Textos argumentativo.docxSesión de aprendizaje Planifica Textos argumentativo.docx
Sesión de aprendizaje Planifica Textos argumentativo.docx
 

Gulp 0.11

  • 1. Gu´ Linux de Programaci´n (GULP) ıa o Sven Goldt Sven van der Meer Scott Burkett Matt Welsh Versi´n 0.4 o Marzo 1995 0 ...Nuestro objetivo permanente: mejorar nuestro conocimiento de C, explorar extra˜os comandos Unix y to boldly code where no one has man page 4. n
  • 2. 2
  • 3. ´ Indice General 1 El sistema operativo Linux 9 2 El n´ cleo de Linux u 11 3 El paquete libc de Linux 13 4 Llamadas al sistema 15 5 Una llamada multiuso: “ioctl” 17 6 Comunicaci´n entre procesos en Linux o 19 6.1 Introducci´n . . . . . . . . . . . . . . . . . . . . . o . . . . . . . 19 6.2 Pipes UNIX Semi-d´ plex . . . . . . . . . . . . . u . . . . . . . 19 6.2.1 Conceptos b´sicos . . . . . . . . . . . . . a . . . . . . . 19 6.2.2 Creaci´n de tuber´ en C . . . . . . . . . o ıas . . . . . . . 21 6.2.3 Tuber´ la forma f´cil de hacerlo . . . . ıas, a . . . . . . . 27 6.2.4 Operaciones at´micas con tuber´ . . . . o ıas . . . . . . . 31 6.2.5 Notas acerca de las tuber´ semi-d´ plex: ıas u . . . . . . . 32 6.3 Tuber´ con Nombre (FIFO - First In First Out) ıas . . . . . . . 32 6.3.1 Conceptos b´sicos . . . . . . . . . . . . . a . . . . . . . 32 6.3.2 Creaci´n de una FIFO . . . . . . . . . . . o . . . . . . . 32 6.3.3 Operaciones con FIFOs . . . . . . . . . . . . . . . . . 34 6.3.4 Acciones Bloqueantes en una FIFO . . . . . . . . . . . 36 6.3.5 La Infame Se˜ al SIGPIPE . . . . . . . . . n . . . . . . . 36 6.4 IPC en Sistema V . . . . . . . . . . . . . . . . . . . . . . . . 36 6.4.1 Conceptos fundamentales . . . . . . . . . . . . . . . . 36 6.4.2 Colas de Mensajes . . . . . . . . . . . . . . . . . . . . 39 6.4.3 Sem´foros . . . . . . . . . . . . . . . . . . a . . . . . . . 57 6.4.4 Memoria Compartida . . . . . . . . . . . . . . . . . . 77 7 Programaci´n del Sonido o 87 7.1 Programaci´n del altavoz interno . . . . . . . . . . . . . . . . 87 o 7.2 Programaci´n de una Tarjeta de sonido . . . . . . . . . . . . 88 o 3
  • 4. 4 ´ INDICE GENERAL 8 Gr´ficos en modo car´cter a a 89 8.1 Funciones E/S en la libc . . . . . . . . . . . . . . . . . . . . . 90 8.1.1 Salida con Formato . . . . . . . . . . . . . . . . . . . . 90 8.1.2 Entrada con Formato . . . . . . . . . . . . . . . . . . 92 8.2 La Librer´ Termcap . . . . . . . . . . . . . . . ıa . . . . . . . . 94 8.2.1 Introducci´n . . . . . . . . . . . . . . . o . . . . . . . . 94 8.2.2 Encontrar la descripci´n del terminal . . o . . . . . . . . 94 8.2.3 Lectura de una descripci´n de terminal o . . . . . . . . 95 8.2.4 Capacidades de Termcap . . . . . . . . . . . . . . . . 96 8.3 Ncurses - Introducci´n . . . . . . . . . . . . . . o . . . . . . . . 101 8.4 Inicializaci´n . . . . . . . . . . . . . . . . . . . o . . . . . . . . 103 8.5 Ventanas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 8.6 Salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 8.6.1 Salida con Formato . . . . . . . . . . . . . . . . . . . . 109 8.6.2 Inserci´n de Caracteres/L´ o ıneas . . . . . . . . . . . . . 109 8.6.3 Borrado de Caracteres/L´ ıneas . . . . . . . . . . . . . . 110 8.6.4 Cajas y L´ ıneas . . . . . . . . . . . . . . . . . . . . . . 110 8.6.5 Car´cter de Fondo . . . . . . . . . . . . a . . . . . . . . 112 8.7 Entrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 8.7.1 Entrada con Formato . . . . . . . . . . . . . . . . . . 113 8.8 Opciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 8.8.1 Opciones en la entrada . . . . . . . . . . . . . . . . . . 114 8.8.2 Atributos de la terminal . . . . . . . . . . . . . . . . . 116 8.8.3 ¿C´mo se usa? . . . . . . . . . . . . . . o . . . . . . . . 117 8.9 ¿C´mo borrar ventanas y l´ o ıneas? . . . . . . . . . . . . . . . . 119 8.10 Actualizaci´n de la imagen an la terminal . . . o . . . . . . . . 120 8.11 Atributos de v´ ıdeo y colores . . . . . . . . . . . . . . . . . . . 122 8.12 Coordenadas del cursor y de las ventanas . . . . . . . . . . . 126 8.13 Movi´ndonos por all´ . . . . . . . . . . . . . . . e ı . . . . . . . . 127 8.14 Pads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 8.15 Soft-labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 8.16 Miscel´nea . . . . . . . . . . . . . . . . . . . . a . . . . . . . . 130 8.17 Acceso de Bajo Niv´l . . . . . . . . . . . . . . . e . . . . . . . . 131 8.18 Volcado de Pantalla . . . . . . . . . . . . . . . . . . . . . . . 131 8.19 Emulaci´n Termcap . . . . . . . . . . . . . . . o . . . . . . . . 131 8.20 Funciones Terminfo . . . . . . . . . . . . . . . . . . . . . . . . 132 8.21 Funciones de Depurado . . . . . . . . . . . . . . . . . . . . . 133 8.22 Atributos Terminfo . . . . . . . . . . . . . . . . . . . . . . . . 133 8.22.1 Atributos L´gicos . . . . . . . . . . . . . o . . . . . . . . 133 8.22.2 N´ meros . . . . . . . . . . . . . . . . . . u . . . . . . . . 134 8.22.3 Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . 135 8.23 Esquema de las Funciones de [N]Curses . . . . . . . . . . . . 143
  • 5. ´ INDICE GENERAL 5 9 Programaci´n de los Puertos de o E/S 147 9.1 Programaci´n del Rat´n . . . . o o . . . . . . . . . . . . . . . . . 149 9.2 Programaci´n del M´dem . . . o o . . . . . . . . . . . . . . . . . 150 9.3 Programaci´n de la Impresora . o . . . . . . . . . . . . . . . . . 150 9.4 Programaci´n del Joystick . . . o . . . . . . . . . . . . . . . . . 150 10 Conversi´n de Aplicaciones a Linux o 151 10.1 Introducci´n . . . . . . . . . . . . . . . . . . o . . . . . . . . . . 151 10.2 Gesti´n de Se˜ ales . . . . . . . . . . . . . . o n . . . . . . . . . . 152 10.2.1 Se˜ ales en SVR4, BSD, y POSIX.1 . n . . . . . . . . . . 152 10.2.2 Opciones de Se˜ ales en Linux . . . . n . . . . . . . . . . 153 10.2.3 signal en Linux . . . . . . . . . . . . . . . . . . . . . . 154 10.2.4 Se˜ ales soportadas por Linux . . . . n . . . . . . . . . . 154 10.3 E/S de Terminal . . . . . . . . . . . . . . . . . . . . . . . . . 154 10.4 Control e Informaci´n de Procesos . . . . . o . . . . . . . . . . 155 10.4.1 Rutinas kvm . . . . . . . . . . . . . . . . . . . . . . . 156 10.4.2 ptrace y el sistema de ficheros /proc . . . . . . . . . . 156 10.4.3 Control de Procesos en Linux . . . . . . . . . . . . . . 156 10.5 Compilaci´n Condicional Portable . . . . . o . . . . . . . . . . 157 10.6 Comentarios Adicionales . . . . . . . . . . . . . . . . . . . . . 159 11 Llamadas al sistema en orden alfab´tico e 161 12 Abreviaturas 167
  • 6. • Copyright La Gu´ Linux de Programaci´n es c 1994, 1995 de Sven Goldt ıa o Sven Goldt, Sachsendamm 47b, 10829 Berl´ Alemania ın, < goldt@math.tu − berlin.de > . El cap´ ıtulo 8 es c 1994, 1995 de Sven van der Meer < vdmeer@cs.tu − berlin.de > . El cap´ıtulo 6 es c 1995 de Scott Burkett < scottb@IntN et.net > . El cap´ ıtulo 10 es c 1994, 1995 de Matt Welsh < mdw@cs.cornell.edu > . Tenemos que dar especialmente las gracias a John D. Harper < jharper@uiuc.edu > por revisar en profundidad esta gu´ ıa. Se concede permiso para reproducir este documento, en todo o en parte, bajo las siguientes condiciones: 1. Esta nota de Copyright debe incluirse sin modificaciones. 2. Comparta con los autores cualquier ganancia que obtenga. 3. Los autores no se hacen responsables de cualquier da˜ o producido n en aplicaci´n de los contenidos de este libro. o • Copyright (nota original) The Linux Programmer’s Guide is c 1994, 1995 by Sven Goldt Sven Goldt, Sachsendamm 47b, 10829 Berlin, Germany < goldt@math.tu − berlin.de > . Chapter 8 is c 1994, 1995 by Sven van der Meer < vdmeer@cs.tu − berlin.de > . Chapter 6 is c 1995 Scott Burkett < scottb@IntN et.net > . Chapter 10 is c 1994, 1995 Matt Welsh < mdw@cs.cornell.edu > . Special thanks goes to John D. Harper < jharper@uiuc.edu > for proofreading this guide. Permission to reproduce this document in whole or in part is subject to the following conditions: 1. The copyright notice remains intact and is included. 2. If you make money with it the authors want a share. 3. The authors are not responsible for any harm that might arise by the use of it. • Notas sobre la versi´n castellana o Esta gu´ como cuarto trabajo importante del Proyecto LuCAS, obe- ıa, dece a la demanda de gu´ de programaci´n para Unix/Linux que ve- ıas o nimos observando desde tiempos recientes. Sin embargo, lamentamos que nuestra traducci´n sea tan incompleta como la versi´n original en o o Ingl´s: ciertamente nos gustar´ completarla, sin embargo no hemos e ıa 6
  • 7. ´ INDICE GENERAL 7 podido recibir los permisos necesarios para ello de algunos de sus au- tores originales, al estar actualmente ilocalizables. El proyecto LuCAS agradece el trabajo de traducci´n realizado inicialmente por Pedro Pa- o blo F´brega a 1 , que abarca buena parte del libro. Adem´s, agradecemos a la colaboraci´n prestada por Ignacio Arenaza, C´sar Ballardini y Luis o e Francisco Gonz´lez2 , quienes se han ocupado de la traducci´n del resto a o del libro. Nota: Versi´n de la traducci´n: 0.11 alpha o o Juan Jos´ Amor e 3 , Mayo de 1998. • Pr´logo o Esta gu´ est´ lejos de completarse. ıa a La primera edici´n fue la versi´n 0.1, de septiembre de 1994. Se bas´ en o o o las llamadas al sistema debido a la escased de informaci´n al respecto. o Est´ previsto completarla con la descripci´n de las funciones de librer´ a o ıa y cambios importantes en el n´ cleo, as´ como incursiones en areas u ı ´ como redes, sonido, gr´ficos y entrada/salida as´ a ıncrona. As´ ımismo, se incluir´n en un futuro apuntes sobre c´mo construir librer´ din´micas a o ıas a y acerca de interesantes herramientas para el programador. Esta gu´ solo ser´ un ´xito gracias a la ayuda en forma de informaci´n ıa a e o o de env´ de nuevos cap´ ıo ıtulos. • Introducci´n o En cierta ocasi´n me dispuse a instalar Linux en mi PC para aprender o m´s acerca de administraci´n del sistema. Intent´ instalar un servidor a o e de SLIP pero no trabaj´ con mgetty ni con el shadow. Tuve que par- e chear el sliplogin y funcion´ hasta las nuevas versiones de Linux 1.1. o Nadie me explic´ qu´ hab´ pasado. No hab´ documentaci´n acer- o e ıa ıa o ca de los cambios desde el n´ cleo 0.99 salvo los res´ menes que hac´ u u ıa Russ Nelson, si bien ´stos no me ayudaban demasiado a resolver mis e problemas. La Gu´ Linux de Programaci´n pretende servir para lo que su nombre ıa o implica— para ayudar al programador de Linux a entender las pecu- liaridades de este sistema operativo. Tambi´n deber´ ser util para e a ´ transportar programas de otros sistemas operativos al Linux. Por lo tanto, esta gu´ debe describir las llamadas al sistema y los cambios ıa importantes del n´ cleo que puedan afectar a antiguos programas tales u como aplicaciones de E/S serie o de red. Sven Goldt Gu´ Linux de Programaci´n ıa o 1 Pedro Pablo est´ disponible en pfabrega@arrakis.es a 2 Sus direcciones de correo respectivas son: inaki.arenaza@jet.es, cba- llard@santafe.com.ar y luisgh@cogs.susx.ac.uk 3 Como siempre, en jjamor@ls.fi.upm.es
  • 8. 8 ´ INDICE GENERAL
  • 9. Cap´ ıtulo 1 El sistema operativo Linux En marzo de 1991 Linus Benedict Torvalds compr´ un sistema Multitarea o Minix para su AT. Lo us´ para desarrollar su propio sistema multitarea que o llam´ Linux. En el mes septiembre de 1991 liber´ el primer prototipo por e- o o mail a algunos otros usuarios de Minix en Internet: as´ comenz´ el proyecto ı o Linux. Muchos programadores desde ese punto han apoyado Linux. Han agregado controladores de dispositivos, desarrollado aplicaciones, seg´ n las u normas POSIX. Hoy Linux es muy potente, pero lo mejor es que es gratuito. Se est´n realizando trabajos para transportar Linux a otras plataformas. a 9
  • 10. 10 CAP´ ITULO 1. EL SISTEMA OPERATIVO LINUX
  • 11. Cap´ ıtulo 2 El n´cleo de Linux u La base de Linux es el n´ cleo. Podr´ reemplazar todas las librer´ pero u ıa ıas, mientras quede el n´ cleo, estar´ todav´ Linux. El n´ cleo incorpora contro- u a ıa u ladores de dispositivos, manejo de la memoria, manejo de procesos y manejo de comunicaciones. Los gur´ s del n´ cleo siguen las pautas POSIX que hacen u u la programaci´n a veces m´s f´cil y a veces m´s dif´ o a a a ıcil. Si su programa se comporta de forma diferente en un nuevo n´ cleo de Linux, puede ser porque u se hayan implantado nuevas l´ ıneas marcadas por POSIX. Para m´s informa- a ci´n de la programaci´n sobre el n´ cleo de Linux, lea el documento Linux o o u Kernel Hacker’s Guide. 11
  • 12. 12 CAP´ ´ ITULO 2. EL NUCLEO DE LINUX
  • 13. Cap´ ıtulo 3 El paquete libc de Linux libc: ISO 8859.1, < linux/param.h >, funciones YP, funciones crypt, algunas rutinas shadow b´sicas (por omisi´n no incluidas),... rutinas a o viejas por compatibilidad en libcompat (por omisi´n no activas), o mensajes del error en ingl´s, franc´s o alem´n, rutinas de gesti´n de e e a o la pantalla compatibles bsd 4.4lite en libcurses, rutinas compatibles bsd en libbsd, rutinas de la manipulaci´n de la pantalla en o libtermcap, rutinas del manejo del base de datos en libdbm, rutinas matem´ticas en libm, entradas para ejecutar programas en crt0.o???, a informaci´n del sexo del byte en libieee??? (¿pod´ alguien dar o ıa informaci´n en lugar de re´ o ırse?), espacio de perfiles de usuario, en libgmon. Me gustar´ que alguno de los desarrolladores de la librer´ ıa ıa libc de Linux escribiera este cap´ ıtulo. Todo lo que puedo decir ahora es que va ha haber un cambio del formato de ejecutables a.out a elf (formato ejecutable y enlazable) que tambi´n significa un cambio en la e construcci´n de bibliotecas compartidas. Normalmente se soportan am- o bos formatos, a.out y elf La mayor´ de los elementos del paquete libc de Linux est´n bajo la ıa a Licencia P´ blica GNU, aunque algunos est´n bajo una excepci´n especial u a o de derechos de copia como crt0.o. Para distribuciones comerciales binarias esto significa una restricci´n que prohibe el enlace est´tico de ejecutables. o a El enlace din´mico de ejecutables son de nuevo una excepci´n especial y a o Richard Stallman del FSF coment´: o [. . . ] Pero me parece que debemos permitir de forma ambigua la distribuci´n o de ejecutables enlazados din´micamente *sin* ir acompa˜ados de la librer´as a n ı bibliotecas, con tal de que los ficheros objeto que forman el ejecutable est´n e sin restricci´n seg´n la secci´n 5 [. . . ] Por tanto tomar´ la decisi´n de o u o e o permitirlo. La actualizaci´n del LGPL tendr´ que esperar hasta que tenga o a tiempo para hacer y comprobar una versi´n nueva. o Sven Goldt Gu´ Linux de Programaci´n ıa o 13
  • 14. 14 CAP´ ITULO 3. EL PAQUETE LIBC DE LINUX
  • 15. Cap´ ıtulo 4 Llamadas al sistema Una llamada al sistema es normalmente una demanda al sistema operati- vo (nucleo) para que haga una operaci´n de hardware/sistema espec´ o ıfica o privilegiada. Por ejemplo, en Linux-1.2, se han definido 140 llamadas al sistema. Las llamadas al sistema como close() se implementan en la libc de Linux. Esta aplicaci´n a menudo implica la llamada a una macro que o puede llamar a syscall(). Los par´metros pasados a syscall() son el n´ mero a u de la llamada al sistema seguida por el argumento necesario. Los n´ meros u de llamadas al sistema se pueden encontrar en < linux/unistd.h > mientras que < sys/syscall.h > actualiza con una nueva libc. Si aparecen nuevas lla- madas que no tienen una referencia en libc aun, puede usar syscall(). Como ejemplo, puede cerrar un fichero usando syscall() de la siguiente forma (no aconsejable): #include <syscall.h> extern int syscall(int, ...); int my_close(int filedescriptor) { return syscall(SYS_close, filedescriptor); } En la arquitectura i386, las llamadas al sistema est´n limitadas a 5 ar- a gumentos adem´s del n´ mero de llamada al sistema debido al n´ mero de a u u registros del procesador. Si usa Linux en otra arquitectura puede compro- bar el contenido de < asm/unistd.h > para las macros syscall, para ver cu´ntos argumentos admite su hardware o cuantos escogieron los desarro- a lladores. Estas macros syscall se pueden usar en lugar de syscall(), pero esto no se recomienda ya que esa macro se expande a una funci´n que ya o puede existir en una biblioteca. Por consiguiente, s´lo los desarrolladores o 15
  • 16. 16 CAP´ ITULO 4. LLAMADAS AL SISTEMA del n´ cleo deber´ jugar a con las macros syscall. Como demostraci´n, u ıan o aqu´ tenemos el ejemplo de close() usando una macro syscall. ı #include <linux/unistd.h> _syscall1(int, close, int, filedescriptor); La macro syscall1 expande la funci´n close(). As´ tenemos close() dos veces, o ı una vez en libc y otra vez en nuestro programa. El valor devuelto por syscall() o un una macro syscall es -1 si la llamada al sistema fall´ y 0 en o caso de ´xito. D´le un vistazo a la variable global errno para comprobar que e e ha ocurrido si la llamada al sistama fall´. o Las siguiente llamadas al sistema est´n disponibles en BSD y SYS V a pero no est´n disponibles en Linux: a audit(), auditon(), auditsvc(), fchroot(), getauid(), getdents(), getmsg(), mincore(), poll(), putmsg(), setaudit(), setauid(). Sven Goldt Gu´ Linux de Programaci´n ıa o
  • 17. Cap´ ıtulo 5 Una llamada multiuso: “ioctl” ioctl representa el control de entrada/salida y se usa para manipular un dispositivo de car´cter mediante un descriptor de fichero. El formato de a ioctl es: ioctl(unsigned int fd, unsigned int request, unsigned long argument). El valor devuelto es -1 si ocurri´ un error y un valor mayor o igual que 0 si o la petici´n tuvo ´xito, como cualquier otra llamadas del sistema. El n´ cleo o e u distingue entre ficheros especiales y regulares. Los ficheros especiales se encuentran principalmente en /dev y /proc. Difieren de los ficheros regulares en que esconden una interface a un controlador y no un fichero real (regular) que contiene texto o datos binarios. Esta es la filosof´ UNIX y permite usar ıa operaciones normales de lectura/escritura en cada fichero. Pero si necesita hacer algo m´s con un fichero especial o un fichero regular que puede hacer a ´l con... s´ ioctl. Usted necesitar´ con m´s frecuencia ioctl para ficheros e ı, a a especiales que para ficheros regulares, pero es posible usar ioctl en ficheros regulares tambi´n. e 17
  • 18. 18 CAP´ ITULO 5. UNA LLAMADA MULTIUSO: “IOCTL”
  • 19. Cap´ ıtulo 6 Comunicaci´n entre procesos o en Linux B. Scott Burkett, scottb@intnet.net v1.0, 29 de Marzo de 1995 6.1 Introducci´n o Los medios IPC (Inter-process communication) de Linux proporcionan un m´todo para que m´ ltiples procesos se comuniquen unos con otros. Hay e u varios m´todos de IPC disponibles para los programadores Linux en C: e • Pipes UNIX Half-duplex • FIFOs (pipes con nombre) • Colas de mensajes estilo SYSV • Sem´foros estilo SYSV a • Segmentos de memoria compartida estilo SYSV • Sockets (estilo Berkeley) (no contemplado por ahora) • Pipes Full-duplex (pipes STREAMS) (no contemplado por ahora) Estos medios, cuando se usan de forma efectiva, proporciona una ba- se s´lida para el desarrollo de cliente/servidor en cualquier sistema UNIX o (incluido Linux). 6.2 Pipes UNIX Semi-d´ plex u 6.2.1 Conceptos b´sicos a Simplemente, una tuber´ (pipe) es un m´todo de conexi´n de que une la ıa e o salida est´ndar de un proceso a la entrada est´ndar de otro. Las tuber´ a a ıas 19
  • 20. 20 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX son la mayor de las herramientas de IPC, han estado presentes desde los primeros or´ ıgenes del sistema operativo UNIX. Proporcionan un m´todo de e comunicaciones en un sentido (unidirecional, semi-duplex) entre procesos. Este mecanismo es ampliamente usado, incluso en la l´ınea de comandos UNIX (en la shell): ls | sort | lp Lo anterior es un ejemplo de ’pipeline’, donde se toma la salida de un comando ls como entrada de un comando sort, quien a su vez entrega su salida a la entrada de lp. Los datos corren por la tuber´ semi-duplex, de ıa viajando (virtualmente) de izquierda a derecha por la tuber´ ıa. Aunque la mayor parte de nosotros usamos las tuber´ casi religiosa- ıas mente en las programaciones de scripts de shell, casi nunca nos paramos a pensar en lo que tiene lugar a nivel del n´ cleo. u Cuando un proceso crea una tuber´ el n´ cleo instala dos descriptores ıa, u de ficheros para que los use la tuber´ Un descriptor se usa para permitir ıa. un camino de entrada a la tuber´ (write), mientras que la otra se usa para ıa obtener los datos de la tuber´ (read). A estas alturas, la tuber´ tiene un ıa ıa peque˜ o uso pr´ctico, ya que la creaci´n del proceso s´lo usa la tuber´ para n a o o ıa comunicarse consigo mismo. Considere esta representaci´n de un proceso y o del n´ cleo despu´s de que se haya creado una tuber´ u e ıa: in Proceso Nucleo out Del diagrama anterior, es f´cil ver c´mo se conectan los descriptores. Si a o el proceso env´ datos por la tuber´ (fd0), tiene la habilidad obtener (leer) ıa ıa esa informaci´n de fd1. Sin embargo, hay un objetivo m´s amplio sobre o a el esquema anterior. Mientras una tuber´ conecta inicialmente un proceso ıa a s´ mismo, los datos que viajan por la tuber´ se mueven por el n´ cleo. ı ıa u Bajo Linux en particular, las tuber´ se representan realmente de forma ıas interna con un inodo v´lido. Por supuesto, este inodo reside dentro del a n´ cleo mismo, y no dentro de los l´ u ımites de cualquier sistema de archivos f´ ısico. Este punto particular nos abrir´ algunas puertas de E/S bastante a pr´cticas, como veremos un poco m´s adelante. a a A estas alturas, la tuber´ es bastante in´ til. Despu´s de todo ¿por ıa u e qu´ el problema de crear una ca˜ er´ si estamos s´lo hablando con nosotros e n ıa o
  • 21. ´ 6.2. PIPES UNIX SEMI-DUPLEX 21 mismos? Ahora, el proceso de creaci´n bifurca un proceso hijo. Como o un proceso hijo hereda cualquier descriptor de fichero abierto del padre, ahora tenemos la base por comunicaci´n multiprocesos (entre padre e hijo). o Considere ´ste versi´n actualizada de de nuestro esquema simple: e o in in Proceso Nucleo Proceso Padre Hijo out out Arriba, vemos que ambos procesos ahora tienen acceso al descriptor del fichero que constituye la tuber´ Est´ en esa fase, que se debe tomar una de- ıa. a cisi´n cr´ o ıtica. ¿En que direcci´n queremos que viajen los datos? ¿El proceso o hijo env´ informaci´n al padre, o viceversa? Los dos procesos mutuamen- ıa o te est´n de acuerdo en esta emisi´n, y procede a“cerrar” el extremo de la a o ca˜ er´ que no le interesa. Por motivos discusi´n, digamos que el hijo ejecu- n ıa o ta unos procesos, y devuelve informaci´n por la tuber´ al padre. Nuestro o ıa esquema ya revisado aparecer´ como: ıa in in Proceso Nucleo Proceso Padre Hijo out out ¡Ahora la construcci´n de la tuber´ est´ completa! Lo unico que queda o ıa a ´ por hacer es usar la tuber´ Para a acceder a una tuber´ directamente, ıa. ıa podemos usar la misma llamada al sistema que se usa para un fichero I/O de bajo nivel. (las tuber´ est´n representadas internamente como un inodo ıas a v´lido). a Para enviarle datos a la tuber´ usamos la llamada al sistema write(), ıa, y para recuperar datos de la tuber´ usamos la llamada al sistema read(). ıa, ¡Recuerde las llamadas del sistema a los ficheros I/O de bajo-nivel se hacen usando descriptores de fichero! Sin embargo, tenga presente que ciertas llamadas al sistema, como por ejemplo lseek(), no trabaja con descriptores a tuber´ıas. 6.2.2 Creaci´n de tuber´ en C o ıas Crear “tuber´ ıas” con el lenguaje de programaci´n C puede ser un poco m´s o a complejo que en un ejemplo de shell. Para crear una tuber´ simple con C, ıa
  • 22. 22 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX hacemos uso de la llamada al sistema pipe(). Toma un argumento solo, que es una tabla de dos enteros, y si tiene ´xito, la tabla contendr´ dos nuevos e a descriptores de ficheros para ser usados por la tuber´ Despu´s de crear ıa. e una tuber´ el proceso t´ ıa, ıpicamente desdobla a un proceso nuevo (recuerde que el hijo hereda los descriptores del fichero). LLAMADA AL SISTEMA: pipe(); PROTOTIPO: int pipe( int fd[2] ); RETORNA: 0 si exito ´ -1 si error: errno = EMFILE (no quedan descriptores libres) EMFILE (tabla de ficheros del sistema llena) EFAULT (el vector fd no es v´lido) a NOTAS: fd[0] es para leer, fd[1] es para escribir El primer del vector fd (elemento 0) est´ fijado y abierto para lectura, a mientras el segundo entero (elemento 1) est´ fijado y abierto para escritura. a Visualmente hablando, la salida de fd1 se vuelve la entrada para fd0. Una vez m´s, todo datos que se mueven por la tuber´ los hacen por el n´ cleo. a ıa u #include <stdio.h> #include <unistd.h> #include <sys/types.h> main() { int fd[2]; pipe(fd); . . } Recuerde que un nombre de vector en C es un puntero a su primer miembro. Es decir, fd es equivalente a &fd0. Una vez hemos establecido la tuber´ entonces desdoblamos (fork) nuestro nuevo proceso hijo: ıa, #include <stdio.h> #include <unistd.h> #include <sys/types.h> main() {
  • 23. ´ 6.2. PIPES UNIX SEMI-DUPLEX 23 int fd[2]; pid_t childpid; pipe(fd); if((childpid = fork()) == -1) { perror("fork"); exit(1); } . . } Si el padre quiere recibir datos del hijo, debe cerrar fd1, y el hijo debe cerrar fd0. Si el padre quiere enviarle datos al hijo, debe cerrar fd0, y el hijo debe cerrar fd1. Como los descriptores se comparten entre el padre y hijo, siempre debemos estar seguros cerrar el extremo de ca˜ er´ que no n ıa nos interesa. Como nota t´cnica, nunca se devolver´ EOF si los extremos e a innecesarios de la tuber´ no son explicitamente cerrados. ıa #include <stdio.h> #include <unistd.h> #include <sys/types.h> main() { int fd[2]; pid_t childpid; pipe(fd); if((childpid = fork()) == -1) { perror("fork"); exit(1); } if(childpid == 0) { /* El hijo cierra el descriptor de entrada */ close(fd[0]); } else
  • 24. 24 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX { /* El padre cierra el descriptor de salida */ close(fd[1]); } . . } Como se mencion´ previamente, una vez se ha establecido la tuber´ los o ıa, descriptores de fichero se tratan como descriptores a ficheros normales. /***************************************************************************** Parte de la "Guia Linux de Programacion - Capitulo 6" (C)opyright 1994-1995, Scott Burkett ***************************************************************************** MODULO: pipe.c *****************************************************************************/ #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(void) { int fd[2], nbytes; pid_t childpid; char string[] = "Hola a todos!n"; char readbuffer[80]; pipe(fd); if((childpid = fork()) == -1) { perror("fork"); exit(1); } if(childpid == 0) { /* Cierre del descriptor de entrada en el hijo */ close(fd[0]); /* Enviar el saludo via descriptor de salida */
  • 25. ´ 6.2. PIPES UNIX SEMI-DUPLEX 25 write(fd[1], string, strlen(string)); exit(0); } else { /* Cierre del descriptor de salida en el padre */ close(fd[1]); /* Leer algo de la tuberia... el saludo! */ nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); printf("Received string: %s", readbuffer); } return(0); } A menudo, los descriptores del hijo son duplicados en la entrada o salida est´ndares. El hijo puede entonces hacer exec() con otro programa, que a hereda los stream est´ndar. Observe la llamada al sistema dup(): a LLAMADA AL SISTEMA: dup(); PROTOTIPO: int dup( int oldfd ); RETORNA: nuevo descriptor si hay exito ´ -1 si error: errno = EBADF (oldfd no es un descriptor valido) EBADF (newfd se sale del rango) EMFILE (Hay demasiados descriptores en el proceso abie NOTAS: <el antiguo descriptor no se cierra! Asi podemos intercambiarlos Aunque el descriptor viejo y el reci´n creado se puede intercambiar, e normalmente cerraremos primero uno de los stream est´ndar. La llamada al a sistema dup() usa el n´ mero descriptor m´s bajo no utilizado para el nuevo u a descriptor. Considere lo siguiente: . . childpid = fork(); if(childpid == 0) { /* Cerrar la entrada estandar en el hijo */ close(0);
  • 26. 26 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX /* Duplicar sobre esta la salida de la tuberia */ dup(fd[0]); execlp("sort", "sort", NULL); } Como el descriptor de fichero 0 (stdin) se cerr´, la llamada a dup() o duplic´ el descriptor de la entrada de la tuber´ (fd0) hacia su entrada o ıa est´ndar. Entonces hacemos una llamada a execlp() recubrir el segmento a de texto (c´digo) del hijo con el del programa. ¡Desde no hace mucho los o programas exec heredan los stream est´ndares de sus or´ a ıgenes, realmente hereda el lado de la entrada de la tuber´ como su entrada est´ndar! Ahora, ıa a cualquier cosa que el padre original procesa lo env´ a la tuber´ va en la ıa ıa, facilidad de la clase. Hay otra llamada al sistema, dup2 (), que se puede usar tambi´n. Esta e llamada particular tiene su origen con la Versi´n 7 de UNIX, se realiz´ por o o una versi´n de BSD y ahora es requerida por el est´ndar POSIX. o a LLAMADA AL SISTEMA: dup2(); PROTOTIPO: int dup2( int oldfd, int newfd ); RETORNA: nuevo descriptor si hay exito ´ -1 si error: errno = EBADF (oldfd no es descriptor v´lido) a EBADF (newfd est´ fuera de rango) a EMFILE (demasiados descriptores abiertos) NOTAS: <el descriptor antiguo es cerrado con dup2()! Con esta particular llamada, tenemos la operaci´n de cerrado, y la du- o plicaci´n del descriptor actual, relacionado con una llamada al sistema. o Adem´s, se garantiza el ser at´mica, que esencialmente significa que nunca a o se interrumpir´ por la llegada de una se˜ al. Toda la operaci´n transcurrir´ a n o a antes de devolverle el control al n´ cleo para despachar la se˜ al. Con la lla- u n mada al sistema dup() original, los programadores ten´ que ejecutar un ıan close() antes de llamarla. Esto resultaba de dos llamadas del sistema, con un grado peque˜ o de vulnerabilidad en el breve tiempo que transcurre entre n ellas. Si llega una se˜ al durante ese tiempo, la duplicaci´n del descriptor n o fallar´ Por supuesto, dup2 () resuelve este problema para nosotros. ıa. Considere: . . childpid = fork();
  • 27. ´ 6.2. PIPES UNIX SEMI-DUPLEX 27 if(childpid == 0) { /* Cerrar entrada estandar, duplicando a esta la salida de datos de la tuberia */ dup2(0, fd[0]); execlp("sort", "sort", NULL); . . } 6.2.3 Tuber´ ıas, la forma f´cil de hacerlo a Si de todo lo visto anteriormente parece enredada la forma de crear y utilizar tuber´ hay una alternativa: ıas, FUNCI´N DE LIBRER´A: popen(); O I PROTOTIPO: FILE *popen ( char *comando, char *tipo); RETORNA: si hay exito, nuevo "stream" de fichero ´ si no hay exito, NULL (por fallo en llamada pipe() o fork() ). ´ NOTAS: crea una tuber´a, y realiza las llamadas fork/exec ı seg´n el "comando" pasado como argumento. u Esta funci´n est´ndar de la biblioteca crea una tuber´ semi-duplex lla- o a ıa mando a pipe() internamente. Entonces adesdobla un proceso hijo, abre una shell Bourne y ejecuta el argumento “command” en la shell. La direcci´n o del flujo de datos se determina por el segundo argumento, “type”. Puede ser “r” o “w”, para “read” o “write”. ¡No pueden ser ambos!. Bajo Linux la tuber´ se abrir´ seg´ n el modo especificado por el primer car´cter del ıa a u a argumento “type”. As´ si trata de pasar “rw”, s´lo lo abre en modo “read”. ı, o Mientras esta funci´n de la biblioteca ejecuta realmente parte del trabajo o sucio por usted, hay un inconveniente substancial. Pierde parte del control que ten´ con el uso de la llamada al sistema pipe(), y la manipulaci´n de ıa o fork/exec por usted mismo. Sin embargo, como la shell de Bourne se usa directamente, la expansi´n de metacaracteres de la shell (incluso plantillas) o est´ permitida dentro del argumento “comando”. a Las tuber´ que se crean con popen() se debe cerrar con pclose(). Por ıas ahora, probablemente se habr´ dado cuenta de que popen/pclose comparten a un parecido llamativo con las funciones I/O stream de fichero normal fopen() y fclose().
  • 28. 28 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX FUNCI´N DE LIBRER´A: pclose(); O I PROTOTIPO: int pclose( FILE *stream ); RETORNA: el c´digo de retorno de la llamada wait4() o -1 si el "stream" pasado no es v´lido, o la llamada wait4() falla a NOTAS: espera a que el proceso que escribe en la tuberia termine, y luego cierra el "stream". La funci´n pclose() ejecuta un wait4() en el proceso desdoblado por o popen(). Cuando vuelve, destruye la tuber´ y el stream de fichero de salida. ıa Una vez m´s, es sin´nimo de la funci´n fclose() para ficheros E/S normales a o o de stream. Considere este ejemplo, que abre una tuber´ al comando sort, y ordena ıa un array de cadena de caracteres.: /***************************************************************************** Parte de la "Guia Linux de Programacion - Capitulo 6" (C)opyright 1994-1995, Scott Burkett ***************************************************************************** MODULO: popen1.c *****************************************************************************/ #include <stdio.h> #define MAXSTRS 5 int main(void) { int cntr; FILE *pipe_fp; char *strings[MAXSTRS] = { "eco", "bravo", "alpha", "charlie", "delta"}; /* Crea una tuberia de un sentido llamando a popen() */ if (( pipe_fp = popen("sort", "w")) == NULL) { perror("popen"); exit(1); } /* Bucle de proceso */ for(cntr=0; cntr<MAXSTRS; cntr++) {
  • 29. ´ 6.2. PIPES UNIX SEMI-DUPLEX 29 fputs(strings[cntr], pipe_fp); fputc(’n’, pipe_fp); } /* Cierra la tuberia */ pclose(pipe_fp); return(0); } Como popen() usa la shell para hacer su enlace, ¡todas las expansiones de caracteres y metacaracteres de la shell est´n disponibles para su uso! a Adem´s, t´cnicas m´s avanzadas tales como redirecci´n, e incluso la salida a e a o por tuber´ se puede utilizar con popen(). Considere el siguiente ejemplo: ıa popen("ls ~scottb", "r"); popen("sort > /tmp/foo", "w"); popen("sort | uniq | more", "w"); Considere este peque˜ o programa como otro ejemplo de popen(), que n abre dos tuber´ (una a la orden ls, el otro a sort): ıas /***************************************************************************** Parte de la "Guia Linux de Programacion - Capitulo 6" (C)opyright 1994-1995, Scott Burkett ***************************************************************************** MODULO: popen2.c *****************************************************************************/ #include <stdio.h> int main(void) { FILE *pipein_fp, *pipeout_fp; char readbuf[80]; /* Crea una tuberia de un sentido llamando a popen() */ if (( pipein_fp = popen("ls", "r")) == NULL) { perror("popen"); exit(1); }
  • 30. 30 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX /* Crea una tuberia de un sentido llamando a popen() */ if (( pipeout_fp = popen("sort", "w")) == NULL) { perror("popen"); exit(1); } /* Bucle de proceso */ while(fgets(readbuf, 80, pipein_fp)) fputs(readbuf, pipeout_fp); /* Cierre de las tuberias */ pclose(pipein_fp); pclose(pipeout_fp); return(0); } Para nuestra demostraci´n final de popen(), creamos un programa o gen´rico que abre una tuber´ entre una orden pasada y un nombre de e ıa fichero: /***************************************************************************** Parte de la "Guia Linux de Programacion - Capitulo 6" (C)opyright 1994-1995, Scott Burkett ***************************************************************************** MODULO: popen3.c *****************************************************************************/ #include <stdio.h> int main(int argc, char *argv[]) { FILE *pipe_fp, *infile; char readbuf[80]; if( argc != 3) { fprintf(stderr, "USO: popen3 [comando] [archivo]n"); exit(1); } /* Abrir el fichero de entrada */ if (( infile = fopen(argv[2], "rt")) == NULL)
  • 31. ´ 6.2. PIPES UNIX SEMI-DUPLEX 31 { perror("fopen"); exit(1); } /* Crear una tuberia de un sentido llamando a popen() */ if (( pipe_fp = popen(argv[1], "w")) == NULL) { perror("popen"); exit(1); } /* Bucle de proceso */ do { fgets(readbuf, 80, infile); if(feof(infile)) break; fputs(readbuf, pipe_fp); } while(!feof(infile)); fclose(infile); pclose(pipe_fp); return(0); } Pruebe este programa, con las llamadas siguientes: popen3 sort popen3.c popen3 cat popen3.c popen3 more popen3.c popen3 cat popen3.c | grep main 6.2.4 Operaciones at´micas con tuber´ o ıas Para que una operaci´n se considere “at´mica”, no se debe interrumpir de o o ninguna manera. Todo su funcionamiento ocurre de una vez. La norma POSIX indica en /usr/include/posix1 lim.h que el tama˜ o m´ximo del n a buffer para una operaci´n at´mica en una tuber´ es: o o ıa #define _POSIX_PIPE_BUF 512 Hasta 512 bytes se pueden escribir o recuperar de una tuber´ ıa at´micamente. Cualquier cosa que sobrepase este l´ o ımite se partir´. Bajo Li- a nux sin embargo, se define el l´ ımite at´mico operacional en “linux/limits.h” o como:
  • 32. 32 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX #define PIPE_BUF 4096 Como puede ver, Linux adapta el n´ mero m´ u ınimo de bytes requerido por POSIX, y se le pueden agregar bastantes. La atomicidad del funcionamiento de tuber´ se vuelve importante cuando implica m´s de un proceso (FIFOS). ıa a Por ejemplo, si el n´ mero de bytes escritos en una tuber´ excede el l´ u ıa ımite at´mico para una simple operaci´n, y procesos m´ ltiples est´n escribiendo o o u a en la tuber´ los datos ser´n “intercalados” o “chunked”. En otras palabras, ıa, a un proceso insertar´ datos en la tuber´ entre la escritura de otro. ıa ıa 6.2.5 Notas acerca de las tuber´ semi-d´ plex: ıas u • Se pueden crear tuber´ de dos direcciones abriendo dos tuber´ y ıas ıas, reasignado los descriptores de fichero al proceso hijo. • La llamada a pipe() debe hacerse ANTES de la llamada a fork(), o los hijos no heredar´n los descriptores (igual que en popen()). a • Con tuber´ semi -duplex, cualquier proceso conectado debe compar- ıas tir el ancestro indicado. Como la tuber´ reside en el n´ cleo, cualquier ıa u proceso que no sea ancestro del creador de la tuber´ no tiene forma de ıa direccionarlo. Este no es el caso de las tuber´ con nombre (FIFOS). ıas 6.3 Tuber´ con Nombre (FIFO - First In First ıas Out) 6.3.1 Conceptos b´sicos a Una tuber´ con nombre funciona como una tuber´ normal, pero tiene al- ıa ıa gunas diferencias notables. • Las tuber´ con nombre existen en el sistema de archivos como un ıas archivo de dispositivo especial. • Los procesos de diferentes padres pueden compartir datos mediante una tuber´ con nombre. ıa • Cuando se han realizados todas las I/O por procesos compartidos, la tuber´ con nombre permanece en el sistema de archivos para un uso ıa posterior. 6.3.2 Creaci´n de una FIFO o Hay varias formas de crear una tuber´ con nombre. Las dos primeras se ıa pueden hacer directamente de la shell.
  • 33. 6.3. TUBER´ IAS CON NOMBRE (FIFO - FIRST IN FIRST OUT) 33 mknod MIFIFO p mkfifo a=rw MIFIFO Los dos comandos anteriores realizan operaciones id´nticas, con una e excepci´n. El comando mkfifo proporciona una posibilidad de alterar los o permisos del fichero FIFO directamente tras la creaci´n. Con mknod ser´ o a necesaria una llamada al comando chmod. Los ficheros FIFO se pueden identificar r´pidamente en un archivo f´ a ısico por el indicador ”p”que aparece en la lista del directorio. $ ls -l MIFIFO prw-r--r-- 1 root root 0 Dec 14 22:15 MIFIFO| Tambi´n hay que observar que la barra vertical (”s´ e ımbolo pipe”) est´ a situada inmediatamente detr´s del nombre de fichero. Otra gran raz´n para a o usar Linux ¿eh? Para crear un FIFO en C, podemos hacer uso de la llamada del sistema mknod(): FUNCI´N DE LIBRER´A: mknod(); O I PROTOTIPO: int mknod( char *nombre, mode_t modo, dev_t disp); RETURNS: 0 si exito, ´ -1 si error: errno = EFAULT (nombre no v´lido) a EACCES (permiso denegado) ENAMETOOLONG (nombre demasiado largo) ENOENT (nombre no v´lido) a ENOTDIR (nombre no v´lido) a (vea la p´gina mknod(3) para m´s informaci´n) a a o NOTES: Crea un nodo del sistema de ficheros (fichero, dispositivo, o FIFO) Dejar´ una discusi´n m´s detallada de mknod() a la p´gina del manual, e o a a pero lo podemos considerear un simple ejemplo de la creaci´n de un FIFO o en C: mknod("/tmp/MIFIFO", S_IFIFO|0666, 0); En este caso el fichero “/tmp/MIFIFO” se crea como fichero FIFO. Los permisos requeridos son “0666”, aunque se ven afectados por la configuraci´n o de umask de la siguiente forma: umask_definitiva = permisos_solicitados & ~umask_inicial Un truco com´ n es usar la llamada del sisterma umask() para borrar u temporalmente el valor de umask:
  • 34. 34 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX umask(0); mknod("/tmp/MIFIFO", S_IFIFO|0666, 0); Adem´s, el tercer argumento de mknod() se ignora salvo que estemos a creando un archivo de dispositivo. En ese caso, se deber´ especificar los ıa n´ meros mayor y menor del fichero de dispositivo. u 6.3.3 Operaciones con FIFOs Las operaciones E/S sobre un FIFOson esencialmente las mismas que para las tuber´ normales, con una gran excepci´n. Se deber´ usar una llamada ıas o ıa o o del sistema pen una funci´n de librer´ para abrir f´ o ıa ısicamente un canal para la tuber´ Con las tuber´ semi-duplex, esto es innecesario, ya que la ıa. ıas tuber´ reside en el n´ cleo y no en un sistemade archivos f´ ıa u ısico. En nuestro ejemplo trataremos la tuber´ como un stream, abi´ndolo con fopen(), y ıa e cerr´ndolo con fclose(). a Consideramos un proceso servidor simple: /***************************************************************************** Parte de la "Guia Linux de Programacion - Capitulo 6" (C)opyright 1994-1995, Scott Burkett ***************************************************************************** MODULO: fifoserver.c *****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <linux/stat.h> #define FIFO_FILE "MIFIFO" int main(void) { FILE *fp; char readbuf[80]; /* Crea el FIFO si no existe */ umask(0); mknod(FIFO_FILE, S_IFIFO|0666, 0); while(1)
  • 35. 6.3. TUBER´ IAS CON NOMBRE (FIFO - FIRST IN FIRST OUT) 35 { fp = fopen(FIFO_FILE, "r"); fgets(readbuf, 80, fp); printf("Cadena recibida: %sn", readbuf); fclose(fp); } return(0); } Como un FIFO bloquea por defecto, ejecute el servidor en segundo plano tras compilarlo: $ fifoserver& Discutiremos la acci´n de bloqueo de un FIFO en un momento. Primero o considrearemos el siguiente cliente simple enfrentado a nuestro servidor: /***************************************************************************** Parte de la "Guia Linux de Programacion - Capitulo 6" (C)opyright 1994-1995, Scott Burkett ***************************************************************************** MODULO: fifoclient.c *****************************************************************************/ #include <stdio.h> #include <stdlib.h> #define FIFO_FILE "MIFIFO" int main(int argc, char *argv[]) { FILE *fp; if ( argc != 2 ) { printf("USO: fifoclient [cadena]n"); exit(1); } if((fp = fopen(FIFO_FILE, "w")) == NULL) { perror("fopen"); exit(1); }
  • 36. 36 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX fputs(argv[1], fp); fclose(fp); return(0); } 6.3.4 Acciones Bloqueantes en una FIFO Normalmente, el bloqueo ocurre en un FIFO. En otro palabras, si se abre el FIFO para lectura, el proceso esar´ ”bloqueado”hasta que cualquier otro a proceso lo abra para escritura. Esta acci´n funciona al rev´s tambi´n. Si este o e e comportamiento no nos interesa, se puede usar la bandera O NONBLOCK en la llamada a open() para desactivar la acci´n de bloqueo por defecto. o En el caso de nuestro servidor simple, lo hemos puesto en segundo plano, y permito hacer su bloqueo all´ La alternativa estar´ saltar a otra consola ı. ıan virtual y ejecutar el cliente, cambiando de un lado a otro para ver la acci´n o resultante. 6.3.5 La Infame Se˜ al SIGPIPE n En una ultima nota, las tuber´ deber´ tener a un lector y un escritor. ´ ıas ıan Si un proceso trata de escribir en una tuber´ que no tiene lector, el n´ cleo ıa u enviar´ la se˜ al SIGPIPE. Esto es imperativo cuando en la tuber´ se ven a n ıa envueltos m´s dos procesos. a 6.4 IPC en Sistema V 6.4.1 Conceptos fundamentales Con Unix Sistema V, AT&T introdujo tres nuevas formas de las facilidades IPC (colas de mensajes, sem´foros y memoria compartida). Mientras que el a comit´ POSIX aun no ha completado su estadarizaci´n de estas facilidades, e o la mayor´ de las implementaciones soportan ´stas. Adem´s, Berkeley (BSD) ıa e a usa sockets como su forma primaria de IPC, m´s que los elementos del a Sistema V. Linux tiene la habilidad de usar ambas formas de IPC (BSD y System V), aunque no se discutir´n los socket hasta el ultimo cap´ a ´ ıtulo. La implementaci´n para Linux del IPC System V fue escrita por Krishna o Balasubramanian, en balasub@cis.ohio-state.edu. Identificadores IPC Cada objeto IPC tiene un unico identificador IPC asociado con ´l. Cuando ´ e decimos “objeto IPC”, hablamos de una simple cola de mensaje, sem´foro a o segmento de memoria compartida. Se usa este identificador, dentro del
  • 37. 6.4. IPC EN SISTEMA V 37 n´ cleo, para identificar de forma unica un objeto IPC. Por ejemplo, para u ´ acceder un segmento particular memoria compartida, lo unico que requiere ´ es el valor ID unico que se le ha asignado a ese segmento. ´ La unicidad de un identificador es importante seg´ n el tipo de obje- u to en cuesti´n. Para ilustrar esto, supondremos un identificador num´rico o e “12345”. Mientras no puede haber nunca dos colas de mensajes, con este mismo identificador existe la posibilidad que existan una cola de mensajes y un segmento de memoria compartida que poseen el mismo identificador num´rico. e Claves IPC ´ Para obtener un identificador unico, debe utilizarse una clave. Esta debe ´ ser conocida por ambos procesos cliente y servidor. Este es el primer paso para construir el entorno cliente/servidor de una aplicaci´n. o Cuando usted llama por tel´fono a alguien, debe conocer su n´mero. e u Adem´s, la compa˜´a telef´nica debe conocer c´mo dirigir su llamada al a nı o o destino. Una vez que el receptor responde a su llamada, la conexi´n tiene o lugar. En el caso de los mecanismos IPC de Sistema V, el “tel´fono” coinci- e de con el tipo de objeto usado. La “compa˜´ telef´nica” o el sistema de nıa o encaminado, se puede equiparar con la clave IPC. La clave puede ser el mismo valor cada vez, incluyendo su c´digo en o la propia aplicaci´n. Esta es una desventaja pues la clave requerida puede o estar ya en usa. Por eso, la funci´n ftok() nos ser´ util para generar claves o a´ no utilizadas para el cliente y el servidor. FUNCI´N DE LIBRER´A: ftok(); O I PROTOTIPO: key_t ftok ( char *nombre, char proj ); RETORNA: nueva clave IPC si hay exito ´ -1 si no hubo exito, dejando errno con el valor de la llamada stat() ´ La clave del valor devuelto de ftok () se genera por la combinaci´n del o n´ mero del inodo y del n´ mero menor de dispositivo del archivo argumento, u u ´ con el car´cter identificador del proyecto del segundo argumento. Este no a garantiza la unicidad, pero una aplicaci´n puede comprobar las colisiones y o reintentar la generaci´n de la clave. o key_t miclave; miclave = ftok("/tmp/miaplic", ’a’); En el caso anterior el directorio /tmp/miaplic se combina con la letra ’a’.Otro ejemplo com´ n es usar el directorio actual: u
  • 38. 38 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX key_t miclave; mykey = ftok(".", ’a’); El algoritmo de la generaci´n de la clave usado est´ completamente a o a la discreci´n del programador de la aplicaci´n. Mientras que tome medi- o o das para prevenir ls condiciones cr´ ıticas, bloqueos, etc, cualquier m´todo es e viable. Para nuestros prop´sitos de demostraci´n, usaremos ftok(). Si supo- o o nemos que cada proceso cliente estar´ ejecut´ndose desde un unico directorio a a ´ “home”, las claves generadas deben bastar por nuestras necesidades. El valor clave, sin embargo, se obtiene, se usa una llamada al sistema IPC para crear u obtener acceso a los objetos IPC. Comando ipcs El comando ipcs puede utilizarse para obtener el estado de todos los objetos IPC Sistema V. La versi´n para Linux de esta utilidad tambi´n fue preparada o e por Krishna Balasubramanian. ipcs -q: Mostrar solo colas de mensajes ipcs -s: Mostrar solo los sem´foros a ipcs -m: Mostrar solo la memoria compartida ipcs --help: Otros argumentos Por defecto, se muestran las tres categor´ ıas. Consid´rese el siguiente e ejemplo de salida del comando ipcs: ------ Shared Memory Segments -------- shmid owner perms bytes nattch status ------ Semaphore Arrays -------- semid owner perms nsems status ------ Message Queues -------- msqid owner perms used-bytes messages 0 root 660 5 1 Aqu´ vemos una simple cola mensaje que tiene un identificador “ 0.” Es ı propiedad del root, y tiene permisos en octal de 660, o -rw-rw--. Hay un mensaje en la cola, y ese mensaje tiene un tama˜ o del total de 5 bytes. n Los comandos ipcs son una herramienta muy potente que proporciona una leve introducci´n en los mecanismos de almacenamiento del n´ cleo para o u objetos IPC. Apr´ndalo, uselo, reverencielo. e ´
  • 39. 6.4. IPC EN SISTEMA V 39 El Comando ipcrm Se puede usar el comando ipcrm para quitar un objeto IPC del n´ cleo. u Mientras que los objetos IPC se pueden quitar mediante llamadas al sistema en el c´digo del usuario (veremos c´mo en un momento),aparece a menudo o o la necesidad, sobre todo en ambientes del desarrollo, de quitar objetos IPC a mano. Su uso es simple: ipcrm <msg | sem | shm> <IPC ID> Simplemente especifique si el objeto a eliminar es una cola de mensaje ( em msg), un sem´foro (sem), o un segmento de memoria compartida (shm). a El identificador de IPC se puede obtenr mediante los comandos ipcs. Tiene que especificar el tipo de objeto, como los identificadores son unicos entre ´ los del mismo tipo (retome nuestra discusi´n anterior). o 6.4.2 Colas de Mensajes Conceptos B´sicos a Las colas de mensaje se pueden describir mejor como una lista enlazada interior dentro del espacio de direccionamiento del n´ cleo.Los mensajes se u pueden enviar a la cola en orden y recuperarlos de la cola en varias maneras diferentes. Cada cola de mensaje (por supuesto) est´ identificada de forma a unica por un identificador IPC. ´ Estructuras interna y de datos de usuario La clave para comprender totalmente tales temas complejos como el IPC Sistema V es familiarizarse con las distintas estrcturas de datos internas que residen dentro de los confines del n´ cleo mismo.El acceso directo a algunas u de estas estructuras es necesario incluso en las operacions m´s primitivas, a mientras otros residen a un nivel mucho m´s bajo. a Buffer de Mensaje La primera estructura que veremos es la estructura msgbuf. Esta particular estructura de datos puede ser interpretada como una plantilla por datos del mensaje. Mientras que un programador puede elegir si definir estructuras de este tipo, es imperativo que entiende que hay realmente una estructura del tipo msgbuf. Se declara en linux/msg.h como sigue: /* buffer de mensaje para llamadas msgsnd y msgrcv */ struct msgbuf { long mtype; /* tipo de mensaje */ char mtext[1]; /* texto del mensaje */ };
  • 40. 40 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX Hay dos miembros en la estructura msgbuf: mtype El tipo de mensaje, representado por un n´ mero positivo. ¡Y debe ser u un n´ mero positivo! u mtext Los datos del mensaje en s´ mismo. ı La habilidad asignarle a un mensaje dado un tipo, esencialmente le da la capacidad de multiplexar mensajes en una cola sola. Por ejemplo, al proceso cliente se puede asignar a un n´ mero m´gico, que se puede usar como el tipo u a de mensaje para mensajes enviados desde un proceso servidor. El servidor mismo podr´ usar algunos otros n´ meros, que los clientes podr´ usar para ıa u ıan enviarle mensajes. Por otra parte, una aplicaci´n podr´ marcar mensajes o ıa de error como tener un mensaje tipo 1, petici´n de mensajes podr´ ser o ıan tipo 2, etc. Las posibilidades son interminables. En otra nota no se confunda por el nombre demasiado descriptivo asig- nado al elemento dato del mensaje (mtext). Este campo no se restringe a contener s´lo arrays de car´cteres, sino cualquier tipo e dato, en cualquier o a forma. El campo mismo es realmente arbitrario, ya que esta estructura es redefinida por el programador de la aplicaci´n. Considere esta redefinici´n: o o struct my_msgbuf { long mtype; /* Tipo de mensaje */ long request_id; /* Identificador de petici´n */ o struct client info; /* Estructura de informaci´n del cliente */ o }; Aqu´ vemos el tipo de mensaje, como antes, pero el resto de la estructura ı ha sido reemplazado por otros dos elementos, uno de los cuales es otra ´ estructura. Esta es la belleza de las colas de mensajes. El n´ cleo no hace u ninguna traducci´n de datos. Se puede enviar cualquier informaci´n. o o Sin embargo, existe un l´ ımite interior del m´ximo tama˜ o de un mensaje a n dado. En Linux se define ´ste en linux/msg.h como sigue: e #define MSGMAX 4056 /* <= 4056 */ /* Tama~no maximo del mensaje (bytes) */ El mensajes no puede ser mayor de 4,056 bytes en total, incluyendo el miembro mtype, que tiene una longitud de 4 bytes (long).
  • 41. 6.4. IPC EN SISTEMA V 41 Estructura msg del N´ cleo El n´ cleo guarda cada mensaje en la cola u u dentro de la estructura msg. Se define en linux/msg.h como sigue: /* one msg structure for each message */ struct msg { struct msg *msg_next; /* siguiente mensaje de la cola */ long msg_type; char *msg_spot; /* direccion del texto del mensaje */ short msg_ts; /* tama~no del texto del mensaje */ }; msg next Es un puntero al siguiente mensaje de la cola. Se almacenan como ouna lista simple enlazada en el espacio de direcciones del n´ cleo. u msg type ´ Este es el tipo de mensaje, como asignado en la estructura msgbuf del usuario. msg spot Un puntero al inicio del cuerpo del mensaje. msg ts La longitud del texto del mensaje o del cuerpo. Estructura msqid ds del n´ cleo Cada uno de los tres tipos de objetos u IPC tienen una estructura de datos interna que se mantiene por el n´ cleo. u Para las colas de mensaje, es la estructura msqid ds. El n´ cleo crea, alma- u cena, y mantiene un caso de esta estructura por cada cola de mensaje hace cola creada en el sistema. Se define en linux/msg.h de la siguiente forma: /* una estructura msqid por cada cola del sistema */ struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; /* primer mensaje de la cola */ struct msg *msg_last; /* ultimo mensaje */ time_t msg_stime; /* ultimo instante de msgsnd */ time_t msg_rtime; /* ultimo instante de msgrcv */ time_t msg_ctime; /* ultimo instante cambio */ struct wait_queue *wwait; struct wait_queue *rwait; ushort msg_cbytes; ushort msg_qnum;
  • 42. 42 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX ushort msg_qbytes; /* numero maximo de bytes en cola */ ushort msg_lspid; /* pid del ultimo msgsnd */ ushort msg_lrpid; /* pid de la ultima recepcion */ }; Aunque tendr´ raramente que usar la mayor parte de los miembros de es- a ta estructura, daremos una descripci´n breve de est´ para completar nuestra o a visi´n: o msg perm ´ Un caso de la estructura ipc perm, que se define en linux/ipc.h. Este recoge la informaci´n del permiso para la cola de mensaje, incluso los o permisos del acceso, e informaci´n sobre el creador de la cola (uid, o etc). msg first Enlace al primer mensaje de la cola (cabecera de la lista). msg last Enlace al ultimo mensaje de la cola (cola de la lista). ´ msg stime Instante (time t) del ultimo mensaje que se envi´ a la cola. ´ o msg rtime Instante del ultimo mensaje recuperado de la cola. ´ msg ctime Instantedel ultimo cambio hecho a la cola. (hablaremos de esto m´s ´ a tarde). wwait y rwait Punteros a la cola de espera del n´ cleo. Se usan cuando una operaci´n u o sobre una cola de mensajes estima que el proceso entra en el estado de dormido (es decir, la cola est´ llena y el porceso espera una apertura). a msg cbytes N´ mero total number de bytes que hay en la cola (suma de los tama˜ os u n de todos los mensajes). msg qnum N´ mero de mansajes actual en la cola. u
  • 43. 6.4. IPC EN SISTEMA V 43 msg qbytes M´ximo n´ mero de bytes en la cola. a u msg lspid El PID del proceso que env´ el ultimo mensaje. ıa ´ msg lrpid El PID del proceso que recupera el ultimo mensaje. ´ Estructura ipc perm del n´ cleo El n´ cleo guarda informaci´n de per- u u o misos para objetos IPC en una estructura de tipo ipc perm. Por ejemplo, en la estructura interna para una cola de mensaje descrita antes, el miembro de msg perm es de este tipo. Se declara en linux/ipc.h como sigue: struct ipc_perm { key_t key; ushort uid; /* euid y egid del propietario */ ushort gid; ushort cuid; /* euid y egid del creador */ ushort cgid; ushort mode; /* modos de acceso, veanse despues los valores */ ushort seq; /* numero de secuencia del slot */ }; Todo lo anterior es bastante autoexplicativo. Guardado junto con la clave IPC del objeto hay informaci´n sobre el creador y due˜ o del obje- o n to (pueden ser diferentes).Los modos del acceso octal como un unsigned short. Finalmente, la secuencia del slot se guarda al final. Cada vez qye un objeto IPC se cierra mediante una llamada al sistema llama (destruye), este valor se incrementa por el m´ximo n´ mera de objetos IPC que pueden a u residir en un sistema. ¿Tendr´ que usar este valor? No. a NOTA:Hay una excelente exposici´n de este tema, y los asuntos de o seguridad relacionados, en el libro UNIX Network Programming, de Richard Stevens (p´gina 125). a LLAMADA AL SISTEMA: msgget() Para crear una nueva cola de mensajes, o acceder a una existente, usaremos la llamada al sistema msgget(). LLAMADA AL SISTEMA: msgget();
  • 44. 44 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX PROTOTIPO: int msgget ( key_t clave, int msgflg ); RETORNA: Si hay exito, identificador de la cola de mensajes ´ -1 si error: errno = EACCESS (permiso denegado) EEXIST (No puede crearse la cola pues ya exist EIDRM (La cola esta marcada para borrarse) ENOENT (La cola no existe) ENOMEM (No hay memoria para crear la cola) ENOSPC (Se ha superado el limite de colas) NOTAS: El primer argumento de msgget() es el valor clave (en nuestro caso devuelto por una llamada a ftok(). Este valor clave se compara entonces con los valores clave que existen dentro del n´ cleo de otras colas de mensaje. u En ese punto las operaciones de apertura o acceso depende de los contenidos del argumento msgflg. IPC CREAT Crea la cola si aun no existe en el n´ cleo. u IPC EXCL Cuando se usa con IPC CREAT, falla si la cola ya existe. Si usamos solo IPC CREAT, msgget() retornar´ el identificador de una a cola nueva, o bien el de la existente con la misma clave. Si usamos adem´s a IPC EXCL, la llamada crear´ una nueva cola o fallar´ si la cola con esa clave a a ya exist´ La opci´n IPC EXCL es poco util si no se usa combinada con ıa. o ´ IPC CREAT. Es posible incluir en la m´scara un modo opcional octal, pues cada objeto a IPC tiene un esquema de permisos de acceso similar a cualquier archivo del sistema Unix. Creamos una funci´n de envoltura r´pida para abriro crear una cola de o a mensaje: int abrir_cola( key_t keyval ) { int qid; if((qid = msgget( keyval, IPC_CREAT | 0660 )) == -1) { return(-1); } return(qid); }
  • 45. 6.4. IPC EN SISTEMA V 45 N´tese el uso del modo de permisos 0660. Esta peque˜ a funci´n retor- o n o nar´, bien un identificador entero de la cola de mensajes, o -1 si hubo error. a El valor de la clave (keyval) debe ser el unico argumento de la llamada a la ´ funci´n. o LLAMADA AL SISTEMA: msgsnd() Una vez que tenemos el identificador de la cola, podemos empezar a realizar operaciones sobre ella. Para entregar un mensaje a una cola, use la llamada al sistema msgsndl: LLAMADA AL SISTEMA: msgsnd(); PROTOTIPO: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg ); RETORNA: 0 si exito ´ -1 si error: errno = EAGAIN (la cola est´ llena, y se us´ IPC_NOWAIT). a o EACCES (permiso denegado, no se puede escribir) EFAULT (Direcci´n de memoria de msgp inv´lida) o a EIDRM (La cola de mensajes fue borrada) EINTR (Se recibi´ una se~al mientras se esperaba para o n EINVAL (Identificador de cola inv´lido, tipo a no positivo o tama~o de mensaje inv´lido) n a ENOMEM (No hay memoria suficiente para copiar el buffe NOTAS: El primer argumento de msgsnd es nuestro identificador de la cola, de- vuelto por un llamada previa a msgget. El segundo argumento, msgp, es un puntero a nuestro buffer redeclarado y cargado. El argumento msgsz contie- ne el tama˜ o del mensaje en bytes, excluye la longitud del tipo de mensaje n (4 byte). El argumento msgflg se puede poner a cero (ignorado), o: IPC NOWAIT Si la cola del mensaje est´ llena, entonces no se escribe en la cola a el mensaje, y se le devuelve el control la proceso llamador. Si no se especifica, entonces el proceso llamador se suspender´ (bloqueado) a hasta que se puede escribir el mensaje. Creamos otra funci´n de la envoltura por enviar mensajes: o int enviar_msj( int qid, struct mymsgbuf *qbuf ) { int resultado, longitud;
  • 46. 46 CAP´ ´ ITULO 6. COMUNICACION ENTRE PROCESOS EN LINUX /* La longitud es esencialmente el tama~no de la estructura menos sizeof longitud = sizeof(struct mymsgbuf) - sizeof(long); if((resultado = msgsnd( qid, qbuf, length, 0)) == -1) { return(-1); } return(resultado); } Esta peque˜ a funci´n intenta enviar un mensaje almacenado en la direc- n o ci´n pasada (qbuf) a la cola de mensajes identificada por el n´ mero pasado o u en el argumento qid. Aqu´ tenemos un programa de ejemplo que utiliza las ı dos funciones que hemos desarrollado aqu´ ı: #include <stdio.h> #include <stdlib.h> #include <linux/ipc.h> #include <linux/msg.h> main() { int qid; key_t msgkey; struct mymsgbuf { long mtype; /* Tipo de mensaje */ int request; /* Numero de trabajo */ double salary; /* Salario del empleado */ } msg; /* Generamos nuestra clave IPC */ msgkey = ftok(".", ’m’); /* Abrir/crear la cola */ if(( qid = abrir_cola( msgkey)) == -1) { perror("abrir_cola"); exit(1); } /* Preparar mensajes con datos arbitrarios */ msg.mtype = 1; /* !El mensaje debe ser numero positivo! */ msg.request = 1; /* Dato numero 1 */
  • 47. 6.4. IPC EN SISTEMA V 47 msg.salary = 1000.00; /* Dato numero 2 (!mi salario anual!) */ /* !Bombear mensaje! */ if((enviar_msj( qid, &msg )) == -1) { perror("enviar_msj"); exit(1); } } Tras crear/abrir la cola de mensajes, pasamos a preparar el buffer del mensaje con datos de prueba (note la falta de datos de tipo car´cter para a ilustrar nuestro punto sobre env´o de informaci´n binaria). Una simple ı o llamada a enviar msj env´ nuestro mensaje a la cola. ıa Ahora que tenemos un mensaje en la cola, probemos en comando ipcs para comprobar el estado de ´sta. Ahora continuaremos con la discusi´n e o para ver c´mo leer informaci´n del mensaje. Para ello, se utiliza la llamada o o al sistema msgrcv(): LLAMADA AL SISTEMA: msgrcv(); PROTOTIPO: int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msg RETURNS: N´mero de bytes copiados en la cola de mensajes u -1 si error: errno = E2BIG (La longitud del mensaje es mayor que msgsz) EACCES (No hay permiso de lectura) EFAULT (La direcci´n del buffer msgp es incorrecta) o EIDRM (La cola fue eliminada durante la lectura) EINTR (Interrumpido por llegada de se~al) n EINVAL (msgqid inv´lida, o msgsz menor que 0) a ENOMSG (IPC_NOWAIT incluido, y no hay mensajeen la cola disponible para leer) NOTAS: Obviamente, el primer argumento se usa para especificar la cola utiliza- da durante el proceso de recuperaci´n del mensaje (se deber´ haber sido o ıa devuelto por una llamada anterior a msgget). El segundo argumento (msgp) representa la direcci´n de una variable buffer de mensaje para guardar el o mensaje recuperado. El tercer argumento, (msgsz), representa el tama˜ o n de la estructura del buffer del mensaje, excluye la longitud del miembro de mtype. Una vez m´s, se puede calcular ´ste f´cilmente como: a e a msgsz = sizeof(struct mymsgbuf) - sizeof(long); El cuarto argumento (mtype) especifica el tipo de mensaje a recuperar de la cola. El n´ cleo buscar´ la cola por el ultimo mensaje que cuadra con u a ´ el tipo, y le devolver´ a una copia de ´l en la direcci´n apuntada a por el a e o