En este momento, tengo esta mala verificación para ver si se está leyendo una canalización con nombre:
is_named_pipe_being_read() {
local named_pipe="$1"
echo "unlocked" > "$named_pipe" &
pid="$!"
# Wait a short amount of time
sleep 0.25
# Kill the background process. If kill succeeds, then
# the write was blocked
( kill -PIPE "$pid" ) &> /dev/null
}
Si la eliminación funciona (sale con 0), significa que nadie estaba leyendo desde la tubería.
Pero en lugar de tener un retraso de 0,25 segundos e iniciar un proceso innecesario, estoy buscando una manera de verificar la tubería con nombre para ver si está abierta para lectura. ¿Hay alguna forma de determinar si algo se está leyendo?
Nota: No puedo leer desde la canalización en esta llamada, solo puedo escribir en ella (porque con las canalizaciones con nombre no parece respetarse el orden en el que se conectan los lectores, o tal vez sea el lector más reciente el que obtiene los datos). no es el lector más viejo).
Respuesta1
if /bin/echo unlocked 1<>fifo >fifo; then
there are readers
else
no there ain\'t
fi
is_named_pipe_being_read(){ /bin/echo unlocked 1<>"$1" >"$1"; }
Será /bin/echo
eliminado por a SIGPIPE
y devolverá un estado distinto de cero si no hay lectores.
No puede usar el integrado echo
(ni siquiera en un subshell) porque SIGPIPE
quedará atrapado o matará todo el shell.
Al igual que la versión del OP, esto es destructivo. Si tiene GNU dd, puede intentar abrir el archivo con O_NONBLOCK
, a partir de C
:
is_named_pipe_being_read(){ dd oflag=nonblock conv=notrunc,nocreat count=0 of="$1" 2>/dev/null; }
Pero esto no es mucho mejor; Si hay otros escritores en la tubería, el cierre automático del FIFO en la salida del comando hará que todos los lectores obtengan un EOF.
Nota:El uso de pipas con nombre es más una cuestión de masoquismo o pedantería estándar [1]. La API de sockets BSD implementada por los sockets de dominio Unix es incomparablemente mejor (es por eso que gobierna el mundo ;-)), y hay programas como las versiones más nuevas que netcat
también la hacen utilizable desde el shell.
[1] que es derrotado en ejemplos como el anterior oestepor el hecho de que abrir un FIFO en modo rw está "indefinido" según el estándar, aunque se implementó de la misma manera en la mayoría de los sistemas desde hace aproximadamente 30 años)).
Respuesta2
Robé este programa C dehttps://stackoverflow.com/a/20694422/5047085:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<stdlib.h>
#include <sys/stat.h>
#define SERVFIFO "/Users/alex/.locking/ql/locks/a/fifo.lock"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
void syserr(const char *str){
perror(str);
exit(1);
}
int main(int argc, char** argv){
umask(0);
// try to open for write with no readers
int fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);
if (fdw == -1){
syserr("non-blocking open for write with no readers failed");
}
// create a reader - the process itself - non-blocking
int fdr = open(SERVFIFO, O_RDONLY | O_NONBLOCK);
if (fdr == -1){
syserr("non-blocking open for read no writers failed");
}
// try again to open for write but this time with a reader
fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);
if (fdw == -1){
syserr("non-blocking open with readers failed");
}
printf("non-blocking open for write succeeded\n");
close(fdw);
close(fdr);
}
si sale con 0, ¿eso significa que alguien ya está leyendo desde la canalización con nombre? Y si sale con 1, significa que nadie está leyendo.
Esto podría estar mal, pero las pruebas básicas dicen que funciona. La ruta quince está codificada en el programa anterior.