Peso ligero (subconjunto) de la biblioteca C estándar (biblioteca ANSI C)

Estoy portando la biblioteca C estándar para "SO" de metal desnudo (ARM Cortex-M4, ARM GCC). Quiero tener funciones como strlen, sprintf (y asignador de memoria, tal vez), etc.

He portado PDCLib y Newlib. Newlib no es liviano (e intenta implementar operaciones de archivos, etc.). PDCLib no está en desarrollo activo.

Entonces, quiero Microlib exactamente. Pero no es para GCC y código cerrado.

¿Hay algunas alternativas para esto? ¿Y hay algunos "subconjuntos de metal desnudo" de la biblioteca C estándar?

Tuve buenos resultados con newlib-nano. Si quieres más pequeño, me temo que tendrás que ir por el camino de Keil y pagar mucho dinero.

Respuestas (2)

Cuando quiero una biblioteca verdaderamente liviana (y/o que sea segura para subprocesos), generalmente escribo la mía. Esto no es difícil de hacer.

Dado que habla de un "asignador de memoria", permítame sugerir que un par malloc()/free es trivial de escribir, tal vez unas pocas docenas de líneas:

#define STATUSFREE 0
#define STATUSUSED 1
struct tag {
    struct tag * next;
    int status;
};
struct tag * heap;
void free( void * p ) {
    struct tag * ptag= ((struct tag *)p) - 1;
        ptag->status= STATUSFREE;
}
void * malloc( size_t s ) {
    struct tag *ptag, *pnext;
        for ( ptag= heap; ptag != NULL; ptag= ptag->next )
            if (ptag->status == STATUSFREE) {
                for ( pnext= ptag->next; pnext->status == STATUSFREE; pnext= pnext->next )
                    ;
                if ( s <= (size_t) (((char *) pnext) - (char *) (ptag+1)) ) {
                    if ( s <= (size_t) (((char *) pnext) - (char *) (ptag+2)) ) {
                        ptag->next= (struct tag *) (s + (char *) (ptag+1));
                        ptag->next->status= STATUSFREE;
                        ptag->next->next= pnext;
                    } else
                        ptag->next= pnext;
                    ptag->status= STATUSUSED;
                    return ptag+1;
                }
                ptag->next= pnext;
            }
    return NULL;
}

Lo inicializas de la siguiente manera. Primero, configure un bloque fijo de memoria utilizando una asignación de matriz estándar como esta:

static char mspace[1000];

Eso se puede colocar en algún módulo que escriba. Debe asignarse como tiempo de vida estático, por supuesto.

Luego, en otro lugar (como en main()), haces lo siguiente:

((struct tag *) &mspace[0])->status= STATUSFREE;
((struct tag *) &mspace[0])->next= &((struct tag *) &mspace[sizeof(mspace)])[-1];
((struct tag *) &mspace[sizeof(mspace)])[-1].status= STATUSUSED;
((struct tag *) &mspace[sizeof(mspace)])[-1].next= NULL;
heap= (struct tag *) &mspace[0];

Es muy rápido y muy fácil.

strlen() es, por supuesto, mucho más fácil y puede encontrar todo tipo de implementación en la web para eso.

¿El resto? Te recomiendo que también las escribas. Un libro muy, muy útil aquí es el de PJ Plauger (uno de los fundadores de Whitesmiths LTD, compañía compiladora) "The Standard C Library". Consigue una copia. No te arrepentirás. Cubre cosas como sprintf() para usted, que es mucho más complicado y puede implicar el tratamiento con valores de coma flotante al convertir para la salida. (Cuando vuelva a crear sprintf(), obtendrá una gran cantidad de código como resultado de eso, pero solo es necesario si desea una función de biblioteca tan poderosa).

¡Muchas gracias! ¿Tiene repositorios (porque el código bien mantenido con pruebas también es bueno :-))?
@Kuraga Dado que he estado haciendo trabajo integrado durante décadas, incluida la escritura de todo el código del sistema operativo (que a menudo ahora puedo escribir desde cero para que funcione en dos días o menos en cualquier sistema dado), tengo mucho código fuente de varios proyectos que retengo aquí. Cuando necesito algo, busco los proyectos y extraigo los bits que necesito. Sin embargo, cada biblioteca es personalizada para el proyecto. La razón se debe en parte a que parte del trabajo que hago es médico y CADA LÍNEA de código debe ser examinada minuciosamente. Lanzar código no utilizado es "malo". Casi nunca uso las bibliotecas C de los compiladores.
@Kuraga Code que escribo sigue funcionando después de 30 años en algunos casos. Las solicitudes completas que escribo solo funcionan. Recibí una llamada de un cliente que había estado usando mi software con decenas de miles de sus propios clientes durante 20 años, llamándome para decirme que no se ha encontrado ni un solo error confirmado en mi código en todo ese tiempo. Pero simplemente no he tenido tiempo de organizar y documentar mi código para que otros lo usen bien. Eso requiere MUCHO esfuerzo adicional Y tiempo de reflexión para asegurarme de transmitir todo lo que se necesitaría para que otros lo usen.
¿Por qué se molestaría siquiera con malloc, ya que se trata de sistemas integrados bare metal? malloc no tiene ningún sentido de usar, mira esto .
@Lundin Mi respuesta fue abordar una pregunta específica del OP. Hágale su pregunta al OP.
@jonk Nadie más que tú mencionaste malloc. La implementación de su propia biblioteca es una posible respuesta a la pregunta del OP, pero no hay ninguna razón por la que implementaría funciones de la biblioteca estándar que no tiene ningún sentido para usar en sistemas integrados de metal desnudo.
@Lundin interpreté "asignador de memoria" como sugerente.

Deberías echarle un vistazo a musl .

Es liviano y de código abierto, y está diseñado para aplicaciones integradas.
No sé si esto satisface exactamente sus requisitos.

¡Gracias por responder! No, es dependiente de Linux pero no bare metal.
@Kuraga Lo siento...