Biblioteca subyacente multiplataforma https://github.com/hujianzhe/util, descárguela y colóquela en el directorio BootServer
Introducción:
El código solo implementa el arranque del nodo de servicio, la programación de tareas y la descripción básica del módulo. No contiene ningún código comercial. Está implementado en C puro. Generalmente se compila en una biblioteca dinámica y sigue siendo extremadamente restringido en términos de funciones de uso. Implementa algunos flujos de protocolo comunes y admite la extensión C++ 20 de rutina sin pila y está aislado de algunos códigos de la biblioteca dinámica de C puro para evitar que C++ contamine la capa del marco y afecte la generación de la biblioteca dinámica.
El código en util es responsable de la multiplataforma, excepto que no requiere la instalación de bibliotecas de terceros.
Introducción al proceso de operación:
El proceso de negocio llama a la biblioteca dinámica compilada por el código y llama a la interfaz correspondiente para su uso. Para obtener detalles sobre el proceso de llamada, consulte el ejemplo del nodo de prueba (main_template en el directorio BootServer es un conjunto de plantillas de código de inicio basadas en procesos).
Varios subprocesos manejan la lectura y escritura de E/S de la red dentro del módulo. Un subproceso de aceptación de acceso independiente abrirá inicialmente un subproceso de trabajo para procesar los mensajes internos y los mensajes de red recibidos y enviarlos a la lógica de su código comercial. El subproceso de trabajo utiliza una rutina de pila para programar el procesamiento (consulte a continuación el motivo por el cual no se utiliza una rutina sin pila)
Los subprocesos de trabajo usan corrutinas de pila para la programación de forma predeterminada para mantener la mayor compatibilidad. También puede usar fácilmente corrutinas sin pila de C++ 20 (una implementada en la biblioteca de utilidades) para la programación. Hay corrutinas de pila y procesos sin pila que pueden coexistir.
Introducción al módulo y código de muestra:
1. BootServer: parte del código principal, inicialización y operación necesarias de los nodos de servicio
2. ServiceTemplate: plantilla de código de nodo de servicio, utilizada para escribir su lógica empresarial
3. SoTestClient, SoTestServer: probó nodos y escribió algunos códigos de muestra
4. Cpp20-SoTestServer: nodo de prueba, escribió código de muestra, habilitó la rutina sin pila C++20 en main.cpp (usando un programador de rutinas sin pila C++20 en la biblioteca de utilidades)
Compilar:
compilación VS directa de Windows
Utilice make debug / make release / make asan en Linux/Mac OS X
puesta en marcha:
Edite el archivo de configuración requerido para el inicio del nodo de servicio (consulte la plantilla del archivo de configuración adjunta para conocer el formato específico) y proporcione a cada nodo un archivo de configuración y una identificación única, un nombre de identificación de registro, una IP y un número de puerto.
Windows se abre directamente en VS y el proyecto se configura con los parámetros de inicio <archivo de configuración>
Después de compilar Linux/mac, sh run.sh <proceso de servicio> <archivo de configuración>
Algunas razones e ideas de diseño: P: ¿Por qué no utilizar rutinas sin pila sino rutinas apiladas? R: Es fácil implementar rutinas sin pila en C puro (para obtener código detallado, puede ver el programador de rutinas sin pila implementado en C puro en la biblioteca de utilidades), pero el reciclaje y la persistencia de recursos (especialmente las variables en la pila están sujetas a la repetición de rutinas). -entrada). (esta última situación) es extremadamente difícil. Si desea utilizar rutinas sin pila sin problemas, aún necesita confiar en el soporte del compilador. Esto se ha logrado en C++ 20. También hay una implementación completa del programador de rutinas sin pila de C++ 20 en la biblioteca de utilidades.
P: ¿Por qué la rutina sin pila proporciona esta función extendida en forma de archivo de encabezado?
R: 1. Porque las rutinas sin pila son intrusivas en el código y cambiarán una gran cantidad de formas de firma de funciones.
2. Contiene objetos C++ que no se reconocen en C y la biblioteca dinámica no se puede exportar correctamente.
3. Dado en forma de archivo de encabezado, entregar el permiso de activación de las corrutinas sin pila a la capa de aplicación es la forma en que pienso actualmente para lidiar con la parte de la biblioteca dinámica de C puro sin ninguna contaminación.
P: ¿Se puede reemplazar con otros programadores?
R: El programador del subproceso de trabajo se puede reemplazar. El subproceso de trabajo está diseñado como el operador en ejecución del programador. La interacción entre el subproceso de red y el subproceso de trabajo dentro del marco puede corresponder al comportamiento de programación a través del enlace de interfaz.
P: ¿Se puede reemplazar con otras bibliotecas de red?
R: 1. No se puede reemplazar con otras bibliotecas de red en este momento, pero este problema se consideró al comienzo del diseño. La parte de la red y la parte de programación de tareas están completamente separadas. En el futuro, el comportamiento correspondiente será similar al hilo de trabajo. Se proporcionarán ganchos para reemplazo.
2. Aunque existen muchas bibliotecas de red de terceros, sus enfoques son diferentes. Hay bibliotecas TCP y UDP que se utilizan para el desarrollo de aplicaciones, también hay bibliotecas que desean incluir todo el universo y también hay bibliotecas que implementan toda la pila de protocolos de red en la capa de aplicación, por lo que, de hecho, esta área no está unificada.
3. Si un conjunto de bibliotecas de red ingresa al estándar en el futuro, lo reemplazaré.
P: ¿Por qué no utilizar simplemente C++ como marco?
R: 1. Cuando se escribió este conjunto de código, C ++ 20 aún no había aparecido. En ese momento, la solución de rutina más madura era la rutina de pila. Esto se puede hacer usando C llamando a la API del sistema de plataforma correspondiente.
2. Las funciones que implementará este tipo de marco se han solidificado y el ciclo de vida de los recursos se solidifica mediante el proceso. Basta con implementarlo en C puro (antes había una versión implementada en C ++, y la. el código era más complicado)
3. Si otros módulos llaman a la biblioteca dinámica, aún necesita sellar una interfaz en C
4. Las clases exportadas de C ++ son contagiosas y la ABI no está unificada
P: ¿Se puede seguir desarrollando la capa empresarial utilizando C puro?
R: No se recomienda en absoluto, porque la escritura de procesos asincrónicos y las excepciones lanzadas en módulos escritos en lenguajes de alto nivel hacen que el momento de la destrucción de recursos sea incierto. En este momento, es extremadamente difícil controlar manualmente los recursos usando C puro. Debe usar un lenguaje de nivel superior para manejar estas cosas. Por ejemplo, puede usar C ++ para desarrollar código comercial de nivel superior y su mecanismo RAII puede garantizar la liberación de los recursos correspondientes.
P: Si quiero transformar la "devolución de llamada" del proyecto anterior en una "corrutina", ¿puedo simplemente reemplazar la parte del programador con el punto de llamada correspondiente en el código comercial?
R: No es tan simple. El primero es el problema de la carga de trabajo. Además, ya sea en forma de devolución de llamada o de rutina, la esencia es emitir una solicitud y esperar el resultado. Durante este período, el ciclo de vida de la variable. Es un problema que debe resolverse y debe considerarse cuidadosamente. Si es un puntero sin formato, casi se puede decir que no se puede transformar si el proyecto lo ha utilizado. Medios como std::shared_ptr alargan el ciclo de vida de las variables, por lo que será menos difícil transformarse en una versión de "rutina de pila". Si desea transformarse en una rutina sin pila de C++20, la carga de trabajo es enorme. Equivale a reescribir el proyecto (porque las corrutinas sin pila tienen una fuerte intrusión de código), por lo que se recomienda no transformar proyectos antiguos.
P: ¿Por qué actualmente no se permite migrar la rutina a diferentes subprocesos para su ejecución?
R: La migración de rutinas se puede realizar fácilmente, pero la razón por la que no se proporciona es
1. Las tareas ejecutadas entre rutinas son inciertas, lo que puede provocar que io y el cálculo se mezclen en el mismo hilo de programación.
2. Después de la migración, el mismo proceso de rutina puede ejecutarse en diferentes subprocesos. En este caso, debe asegurarse de que su código no dependa de ninguna variable local de subproceso, pero no puede garantizar que la biblioteca de terceros no utilice variables locales de subproceso. .
P: ¿Asan fallará al compilar y ejecutar?
R: 1. Si está utilizando la rutina apilada predeterminada del marco, definitivamente no es un problema de código. Puede ajustar el tamaño de la pila de rutinas apiladas en el archivo de configuración del nodo (cuando ASAN está habilitado, se consumirá un espacio de pila relativamente grande). entonces existe la posibilidad de que la pila explote)
2. ASAN no es totalmente compatible con la API de rutina apilada (ucontext) en el entorno Unix. Aunque la API de rutina ucontext se ha adaptado a ASAN en el código de utilidad, todavía no puede garantizar al 100% que no habrá problemas de ejecución en ASAN. ambiente (hasta ahora todo bien)
3. En algunas distribuciones de Linux más nuevas, si ASAN genera AddressSanitizer: DEADLYSIGNAL infinitamente, ajuste sudo sysctl vm.mmap_rnd_bits=28 para resolver el problema.
HACER:
1. Realmente no tengo tiempo para escribir una documentación detallada.
2. Brindar soporte para escribir lógica empresarial en lenguaje de secuencias de comandos.