Federico Budassi escribió: > Herr Groucho escribió: >> Lautaro Cozzani escribió: >>> On 8/25/08, Herr Groucho <[EMAIL PROTECTED]> wrote: >>>> Hola. >>>> Para resolver un problema, se me ha planteado la necesidad de hacer >>>> un >>>> programa que acepte conexiones TCP desde equipos embebidos y les lea >>>> datos >>>> que dichos equipos están recabando en campo. >>>> >>>> Actualmente el programa de esos equipos embebidos establece la >>>> conexión >>>> TCP y la mantiene conectada todo el tiempo. Entonces el servidor que >>>> acepta esas conexiones va a tener un socket conectado con cada equipo >>>> todo >>>> el tiempo. Si hay 10 equipos, tendrá 10 conexiones abiertas. Pero qué >>>> pasa >>>> cuando hay 10000 equipos y por lo tanto 10000 conexiones? >>>> >>>> El programa que va a aceptar las conexiones actualmente lanza un >>>> proceso >>>> hijo por cada conexión que acepta. Eso tiene la ventaja de que el >>>> tratamiento de TCP/IP y la implementación del protocolo de aplicación >>>> se >>>> simplifica (sólo hay un socket del cual preocuparse y si el protocolo >>>> de >>>> aplicación tiene que esperar un evento, directamente se puede >>>> bloquear >>>> en >>>> un read() o write() o irse a dormir con timeout en un select()). >>>> Con 10000 conexiones, tendría 10001 procesos. Es esta una estrategia >>>> cuerda para manejar 10000 conexiones? >>>> >>>> - El sistema operativo soportará 10000 procesos (hace unos años el >>>> tamaño >>>> de la tabla de procesos era elegido en tiempo de compilación del >>>> kernel, >>>> en valores miserables como 200)? >>>> - El stack TCP/IP soportará 10000 conexiones? >>>> - Qué le pasará al consumo de memoria? >>>> - Qué le pasará al multitasking si el scheduler tiene que mirar una >>>> tabla >>>> de procesos tan grande cada unas pocas decenas de milisegundos? >>>> >>>> >>>> Qué otras estrategias son concebibles? >>>> - Un único proceso que atienda y maneje todas las conexiones, usando >>>> arreglos para guardar los file descriptors de los sockets, select() >>>> para >>>> esperar que pase algo interesante en alguno de ellos e iteraciones >>>> por >>>> todos lados? >>>> >>>> - Un proceso que lance hijos, cada uno de los cuales maneje unos >>>> pocos >>>> threads (un híbrido entre los 2) >>>> >>>> - Varios sistemas operativos independientes, corriendo en máquinas >>>> (reales >>>> o virtuales) separadas ejecutando cada uno alguno de los programas >>>> anteriores. >>>> >>>> Sugerencias? >>> No se si podras usar la funcion select[1] de C para sockets, pero es >>> justamente para eso. >> >> Sí, select() está mencionado entre una de las opciones en lo que escribí >> más arriba. La pregunta es por qué debería usar esa opción en lugar de >> las >> otras. >> >> Otra opción que no mencioné porque me parece que es lo mismo que usar >> fork() es usar threads, ya que para Linux, los threads igual ocupan >> entradas en la tabla de procesos pues los ve como "procesos tomados con >> liviandad". >> > > ¿Estás seguro de que los ve así a los threads? Tengo entendido que a > partir de la inclusión de las NPTL cambió mucho ese aspecto, y los hilos > comenzaron a ser algo más que procesos bloqueados por spinlocks.
Bueno, hay de los 2: threads totalmente en espacio de usuario y threads con soporte del kernel. Lo que procesos bloqueados con spinlocks, no lo entiendo. Para qué los va a bloquear el kernel? Es problema del espacio de usuario lidiar con la concurrencia en ese caso, no? > O más > bien mucho menos que procesos. Si no me equivoco, cuando vos haces un > fork, se duplica la imagen completa del mapa de memoria del proceso, > pero no es así para los threads. Justamente. Se hace una manganeta con las tablas que describen la memoria virtual y los threads terminan siendo procesos que comparten la memoria de datos (pero no el stack) además de la de código (como en un proceso de verdad fork()eado, en tanto no diverjan). Igual no se nada de las implementaciones disponibles de threads. Hablo sólo desde la teoría. > Yo haría lo siguiente: programaría una aplicación de prueba que no > hiciera nada util, pero que fuera capaz de atender a 10000 conexiones > entrantes. La haría con fork y con la creación de nuevos threads (es > decir, dos "bocetos" de aplicación distintos). También tendrías que > hacer otro programa que cree las conexiones (el simulador de los > controladores embebido). Después de eso, es cuestión de poner a andar la > maquinaria y analizar en detalle los datos de los recursos consumidos > por el servidor con alguna herramienta de profiling, o de la mejor forma > que se te ocurra (lo más simple que se me viene a la mente es un "ps", > pero debe haber algo mejor). Sí, es lo que estoy haciendo. Por eso preguntaba estrategias: iba a hacer un programa implementando cada estrategia para comprar el desempeño. > Me da la impresión de que es medio rebuscado eso de poner varias > máquinas en paralelo, o maquinas virtuales. Una sola debe ser > suficientemente capaz de manejar esa cantidad (con la suficiente memoria > y procesador, claro). > Para mi, threads es el camino. Sino, usá solaris, que ahí si los hilos > son hilos con todas las letras. Eh? Qué diferencia tienen los threads de Solaris con los de Linux para que los de Linux sean más pedorros? Igual, el enfoque mentalmente más natural no es con threads, es con procesos hechos y derechos y con i/o bloqueante. Como la concurrencia está dada por la simultaneidad de operaciones independientes, realmente usar threads por sobre procesos de verdad no suma una ventaja al modelado del problema. -- Herr Groucho ID Jabber: [EMAIL PROTECTED] Clave pública GPG: hkp://pks.lugmen.org.ar Fingerprint GPG: B7BD 0FC7 D9A2 66F3 4EFC 45EE 7DE2 3932 597B 6354
