Inicio Noticias Aplicación de C - Tubos

Aplicación de C – Tubos

Índice de artículos Aplicación de C – Tubi Tubi anónimo

Página 1 de 2

Puede utilizar archivos para comunicarse entre dos procesos, pero las canalizaciones son una solución mucho mejor. Descubra cómo funcionan en este extracto de mi libro sobre el uso de C en un contexto de IoT.

Ahora disponible como libro de bolsillo o libro electrónico de Amazon.

Aplicar C para IoT con Linux

Modo de kernel C, IoT, POSIX y LINUX, modo de usuario y Syscall
Ejecución, permisos y sistema
Extraiga programas en ejecución con señales y excepciones de Systemd
Extracción de señales aritméticas enteras
Resumen: Aritmética básica como operaciones de bits *** NUEVO Punto fijo
Extracto: descriptores simples de archivos aritméticos de coma flotante de coma fija
Resumen: Descriptores simples de archivos El pseudo sistema de archivos
Extracto: los gráficos del pseudo sistema de archivos
Extracto: framebuffer de subprocesamiento de socket
Extraer: variables de condición
Extracto: fecha límite de programación de atómicos centrales y administración de memoria, interferencias y sondeos
ensamblador
Extracto: ensamblador

Véase también el libro adjunto: Fundamental C

En el capítulo, pero no en este extracto:

Descriptores de archivos de archivos Un ejemplo de descriptores y secuencias de acceso aleatorio Uso compartido de archivos fcntl: bloqueo

tubos

El ejemplo anterior (en el intercambio de archivos) utiliza un archivo como medio para enviar datos entre dos procesos. En la mayoría de los casos, una mejor manera de hacer el mismo trabajo es usar una tubería con nombre. Este es también otro ejemplo de cómo un descriptor de archivo se puede aplicar a cosas distintas a los archivos estándar.

Una tubería con nombre, o FIFO, se comporta como un archivo que puede ser abierto, escrito y leído por cualquier proceso que se moleste en abrirlo. La razón por la que se llama FIFO es que funciona como una pila First In First Out. El escritor puede escribir bytes en ella y se almacenan hasta que un lector comienza a leer en el orden en que se escribieron. Puede pensar en el escritor que coloca los bytes en la tubería y en el lector que los extrae del otro lado.

Sin embargo, hay una sutileza. Cuando un proceso escribe en una canalización con nombre, la llamada se bloquea hasta que un proceso abre la canalización para su lectura. Tenga en cuenta que el proceso en realidad no tiene que leer para desbloquear la llamada de escritura, solo necesita estar listo para leer para mover la tubería. Del mismo modo, un intento de leer desde una tubería se bloqueará hasta que haya datos para leer.

Para crear una tubería con nombre, primero debe usar la función mkfifo:

mkfifo (nombre de archivo, permisos);

donde nombre de archivo es el nombre de la tubería y es una ruta completamente calificada que incluye directorios y el permiso son los permisos de acceso a archivos habituales. Tenga en cuenta que mkfifo realmente actúa como si estuviera colocando un archivo en el sistema de almacenamiento, ya que los directorios deben existir, el archivo no debe existir como un archivo estándar y el proceso debe tener permiso para crear un archivo.

Una vez que se ha creado la tubería con nombre, se puede usar como un archivo estándar: se puede abrir y puede usar lectura y escritura para trabajar con él. Sin embargo, solo se puede abrir una tubería con nombre para leer o escribir. Si desea una comunicación bidireccional, debe utilizar dos conductos con nombre. Puede usar la administración de archivos C (flujos) con una tubería con nombre, pero como estos están almacenados en búfer, es más fácil usar descriptores de archivos. También vale la pena saber que puede haber más lectores y escritores que una tubería con nombre.

Puede ver el archivo que corresponde a la tubería en la lista de directorios y se indica como un archivo de tubería mediante ap junto a sus permisos. El archivo de tubería permanece disponible hasta que lo elimine explícitamente. Tenga en cuenta que, aunque la canalización con nombre parece un archivo estándar, el sistema operativo usa memoria para almacenar los datos que pasan a través de él, por lo que es más rápido.

Un ejemplo de una tubería con nombre

Por ejemplo, una versión de canalización con nombre del escritor de archivos anterior es:

#incluye #incluye #incluye #incluye #incluye int main (int argc, char ** argv) {int valor = 0x55555555; mkfifo («/ tmp / myfifo», 0666); int fd = open («/ tmp / myfifo», O_WRONLY); para (;;) {valor = ~ valor; escribir (fd, & valor, 4); printf («W% X», valor); fflush (salida estándar); dormir (1); } return (EXIT_SUCCESS); }

Tenga en cuenta que el archivo debe estar abierto para escritura. Si ejecuta este programa, no verá nada impreso hasta que el lector abra la tubería:

#incluye #incluye #incluye #incluye #incluye int main (int argc, char ** argv) {int valor; int fd = open («/ tmp / myfifo», O_RDONLY); para (;;) {leer (fd, & valor, 4); si ((valor! = 0x555555555) &&
(valor! = ~ 0x555555555)) {printf («% x n», valor);
} printf («R% X», valor); fflush (salida estándar); dormir (1); } return (EXIT_SUCCESS); }

Tenga en cuenta que el reproductor no tiene que crear la tubería con nombre usando mkfifo, ya que la tubería está disponible para otros procesos tan pronto como se crea y permanece disponible hasta que se elimine explícitamente. Las cosas van mal si el archivo de tubería no se ha agregado al sistema de archivos, ya que el lector intentará tratar el archivo como un archivo estándar. En la mayoría de los casos, es una buena idea usar mkfifo, incluso si sabe que el archivo de tubería ya existe.

La última sutileza es que el proceso de escritura se bloqueará hasta que un lector se conecte, pero después de esto, si el lector cierra la tubería o termina, el escritor no se bloqueará pero fallará con un error de tiempo de ejecución. En efecto, se genera una señal SIGPIPE y puede manejarla si desea que el escritor detecte el cierre de la tubería. Es decir, si quieres gestionar el cierre del pipe por parte del lector tienes que cambiar el programa principal del escritor a:

int main (int argc, char ** argv) {int valor = 0x55555555; estructura sigaction psa = {0}; psa.sa_handler = signalHandler; sigaction (SIGPIPE, & psa, NULL); mkfifo («/ tmp / myfifo», 0666); int fd = open («/ tmp / myfifo», O_WRONLY); para (;;) {valor = ~ valor; if (write (fd, & value, 4) <0) {close (fd); fd = open ("/ tmp / myfifo", O_WRONLY); } printf ("W% X", valor); fflush (salida estándar); dormir (1); } return (EXIT_SUCCESS); }

El manejo de señales es estándar, consulte el Capítulo 4, pero tenga en cuenta que cuando el controlador regresa, debe verificar que la escritura devolvió un error para cerrar y volver a abrir la tubería. De esta forma el tubo está listo para ser conectado por otro lector. Un lector puede detectar una tubería cerrada por el escritor verificando cero bytes devueltos de la lectura, que normalmente se bloquea hasta que los datos estén disponibles.

Tenga en cuenta que puede abrir tuberías con nombre en modo sin bloqueo, solo use O_NONBLOCK en la función abierta. En este caso, tanto la lectura como la escritura regresan al mismo tiempo y devuelven un error si el otro extremo de la tubería no está abierto.

Todo esto funciona tan bien con subprocesos como con procesos separados. Puede convertir fácilmente el código de lectura y escritura en un solo proceso con dos subprocesos.

Quizás se pregunte por qué no se necesitan bloqueos cuando se usa una tubería con nombre como en el caso de un archivo real. La respuesta es que escribir en una tubería es una operación atómica, es decir, no se puede detener, siempre que la cantidad de datos sea menor que la PIPE_BUF definida en linux / limits.h (actualmente 4096 bytes). Si mantiene escrituras por debajo de este tamaño, no es necesario bloquear.

Este extracto es de mi libro sobre el uso de C en un contexto de IoT. Este extracto es de mi libro sobre el uso de C en un contexto de IoT.

Marc Gomez
Vine a por tabaco y ya me quedé aquí. Cuando no estoy en el sótano de Tecnopasion suelo pasear por las calles de Barcelona.
RELATED ARTICLES