En Linux, la openat
llamada al sistema se puede utilizar para crear archivos y probar su existencia. Hablando en términos del modelo de memoria C/C++, crear un archivo y verificar su existencia crea una relación de sincronización. Lo que necesito saber es si estas sincronizaciones son secuencialmente consistentes entre sí. (Ciertamente eso espero, pero en realidad no he visto esto documentado en ninguna parte).
Por ejemplo, dados los procesos p1 y p2, y las rutas A y B:
si p1 hace esto: crear(A), entonces crear(B)
y p2 hace esto: intenta abrir (B), luego intenta abrir (A)
y ningún otro proceso interfiere con A o B, ¿es posible que p2 abra B con éxito pero no pueda encontrar A?
Si hay alguna diferencia, podemos asumir que todas las operaciones están dentro de un sistema de archivos.
Respuesta1
Con todas las optimizaciones subyacentes del disco y de la CPU multinúcleo, no es necesariamente posible determinar el orden estricto de una secuencia de operaciones entre dos procesos. Esta es la razón por la que se emplean semáforos si existe la posibilidad de un comportamiento dependiente del tiempo.
Respuesta2
Sólo para archivos en el mismo directorio.
acceso de lectura. Reglas de bloqueo: la persona que llama bloquea el directorio al que estamos accediendo. El candado se comparte.
creación de objetos. Reglas de bloqueo: iguales que las anteriores, pero el bloqueo se considera exclusivo.
eliminación de objetos. Reglas de bloqueo: la persona que llama bloquea al padre, encuentra a la víctima, bloquea a la víctima y llama al método. Las cerraduras son exclusivas.
rename()
eso esnodirectorio cruzado. Reglas de bloqueo: la persona que llama bloquea al padre y encuentra el origen y el destino. En caso de intercambio (conRENAME_EXCHANGE
el argumento in flags), bloquee ambos. En cualquier caso, si el objetivo ya existe, bloquéelo. Si la fuente no es un directorio, bloquéela. Si necesitamos bloquear ambos, bloquéelos en el orden del puntero de inodo. Luego llame al método. Todas las cerraduras son exclusivas. NB: podríamos salirnos con la nuestra bloqueando la fuente (y el destino en el caso de intercambio) compartida.creación de enlaces. Reglas de bloqueo:
bloquear padre
comprobar que la fuente no es un directorio
fuente de bloqueo
llamar al método. Todas las cerraduras son exclusivas.
cambio de nombre entre directorios. El más complicado de todo el grupo. Reglas de bloqueo:
bloquear el sistema de archivos
bloquear a los padres en el orden "antepasados primero".
encontrar origen y destino.
si el padre anterior es igual o descendiente del objetivo, falla con -
ENOTEMPTY
si el nuevo padre es igual o descendiente de la fuente falla con -
ELOOP
Si se trata de un intercambio, bloquee tanto el origen como el destino.
Si el objetivo existe, ciérrelo. Si la fuente no es un directorio, bloquéela. Si necesitamos bloquear ambos, hágalo en el orden del puntero de inodo.
llamar al método. Todos
->i_rwsem
se toman en exclusiva. Nuevamente, podríamos salirnos con la nuestra bloqueando la fuente (y el destino en el caso de intercambio) compartida.Las reglas anteriores obviamente garantizan que todos los directorios que el método va a leer, modificar o eliminar serán bloqueados por la persona que llama.
El bloqueo impone la linealización, por lo que las operacionesen un solo directorioestán totalmente ordenados. Sin embargo, el acceso de lectura (1), la creación de objetos (2) y la eliminación de objetos (3) no requieren bloqueos más amplios que el bloqueo de directorio, por lo que no hay garantías sobre el orden de las operaciones de directorio en diferentes directorios; diferentes observadores pueden ver las historias lineales de los directorios entrelazadas de diferentes maneras.