C lectura y seguridad de subprocesos (linux)

4 minutos de lectura

avatar de usuario
jeremy cochoy

¿Qué pasaría si llamas? read (o writeo ambos) en dos subprocesos diferentes, en el mismo descriptor de archivo (digamos que estamos interesados ​​​​en un archivo local y es un descriptor de archivo de socket), sin usar explícitamente un mecanismo de sincronización.

Leer y escribir son llamadas al sistema, por lo que, en una CPU de un solo núcleo, probablemente sea desafortunado que dos lecturas se ejecuten “al mismo tiempo”. Pero con múltiples núcleos…

¿Qué hará el kernel de Linux?

Y seamos un poco más generales: ¿el comportamiento es siempre el mismo para otros núcleos (como BSD)?

Editar: Según el cerrar documentación, debemos asegurarnos de que el descriptor de archivo no sea utilizado por una llamada al sistema en otro subproceso. Por lo tanto, parece que se requeriría una sincronización explícita antes de cerrar un descriptor de archivo (y, por lo tanto, también alrededor de lectura/escritura si el hilo que puede llamarlo todavía se está ejecutando).

  • No puede no usar un mecanismo de sincronización; el núcleo ya lo hace por usted.

    –Carl Norum

    2 de julio de 2013 a las 17:17

  • Quiero decir, usando explícitamente. Entonces, ¿el núcleo hace todo el trabajo por sí mismo, y leer/escribir/llamar a ambos no requiere ninguna sincronización explícita?

    –Jeremy Cochoy

    2 de julio de 2013 a las 17:20

  • Hasta donde yo sé, sí. En realidad, no soy un experto en kernel de Linux, pero no puedo imaginar que sea de otra manera. Tal vez venga alguien con conocimientos más específicos.

    –Carl Norum

    2 de julio de 2013 a las 17:22

  • no se que pasaria Nunca lo intentaría: tengo hilos que abren su propio fd.

    – Martín James

    2 de julio de 2013 a las 17:24

  • Pruébalo :), háznoslo saber

    – aah134

    2 de julio de 2013 a las 17:32

Cualquier acceso al descriptor de archivos a nivel del sistema (syscall) es seguro para subprocesos en todos los sistemas operativos similares a UNIX convencionales. Aunque dependiendo de la edad, no son necesariamente seguros para señales.

si llamas read, write, accept o similar en un descriptor de archivo de dos tareas diferentes, entonces el mecanismo de bloqueo interno del kernel resolverá la disputa.

Sin embargo, para las lecturas, cada byte solo se puede leer una vez y las escrituras se realizarán en cualquier orden indefinido.

Las funciones de la biblioteca stdio fread, fwrite y compañía. también tienen por defecto un bloqueo interno en las estructuras de control, aunque al usar banderas es posible deshabilitarlo.

  • Hola. ¿Puede publicar una documentación oficial que marque estas funciones como seguras para subprocesos?

    – caballero

    2 de julio de 2013 a las 17:34

  • Sería muy feliz si pudiera agregar enlaces a alguna documentación oficial para leer/escribir/aceptar y fread/fwrite 🙂

    –Jeremy Cochoy

    2 de julio de 2013 a las 17:45

  • Estoy bastante seguro de que glibc no será seguro para subprocesos en fread, fwrite a menos que se vincule con libpthread. Pero, por supuesto, si está utilizando subprocesos, eso ya debería ser cierto.

    – Zan Lince

    2 de julio de 2013 a las 17:46


  • +1. lectura/escritura están definitivamente bien para llamar dos veces a la vez en el mismo fd. Es posible cerrar() mientras el fd todavía está en uso por una llamada al sistema, de hecho, pero generalmente es una mala idea. La única razón por la que la gente parece tener que hacer eso es salir de una llamada al sistema de bloqueo en un fd cerrándolo desde otro hilo, pero debo señalar que ese comportamiento NO ES PORTÁTIL. (Tendría que buscar exactamente a qué sistemas se aplica). Por lo tanto, los documentos tienen razón al desaconsejarlo: aunque el kernel se asegurará de que no detenga el sistema, su aplicación no va a ser feliz.

    – Nicolás Wilson

    2 de julio de 2013 a las 17:50

  • Tenga en cuenta que si llama a escribir en un subproceso mientras otro subproceso está modificando el búfer que se pasa al kernel en la escritura, los datos reales escritos pueden o no contener algunos de los datos modificados que el otro subproceso coloca allí.

    – Chris Dodd

    2 de julio de 2013 a las 20:29

El resultado dependería de cómo los subprocesos estén programados para ejecutarse en ese instante en particular.

Una forma de evitar potencialmente un comportamiento indefinido con subprocesos múltiples es asumir que está realizando operaciones de memoria. Por ejemplo, actualizar una lista enlazada o cambiar una variable, etc.

Si usa mutex/semáforos/bloqueo o algún otro mecanismo de sincronización, debería funcionar según lo previsto.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad