memccpy - ¿Cómo funciona la implementación interna de memcpy?
strcpy (3)
La implementación de memcpy
es altamente específica para el sistema en el que se implementa. Las implementaciones son a menudo asistidas por hardware.
Las instrucciones de movimiento de memoria a memoria no son tan infrecuentes: han existido desde al menos PDP-11
veces, cuando puedes escribir algo como esto:
MOV FROM, R2
MOV TO, R3
MOV R2, R4
ADD LEN, R4
CP: MOV (R2+), (R3+) ; "(Rx+)" means "*Rx++" in C
CMP R2, R4
BNE CP
La línea comentada es aproximadamente equivalente a la de C
*to++ = *from++;
Las CPU memcpy
tienen instrucciones que implementan memcpy
directamente: carga registros especiales con las direcciones de origen y destino, invoca un comando de copia de memoria y deja que la CPU haga el resto.
¿Cómo funciona la función C ''memcpy'' estándar? Tiene que copiar una porción (grande) de RAM a otra área en la RAM. Ya que sé que no puede pasar directamente de RAM a RAM en ensamblaje (con la instrucción mov), entonces supongo que utiliza un registro de CPU como la memoria intermedia cuando copia.
Pero, ¿cómo se copia? Por bloques (¿cómo se copiarían por bloques?), Por bytes individuales (char) o el tipo de datos más grande que tienen (copia en dobles largos, que es de 12 bytes en mi sistema).
EDIT: Ok, aparentemente puede mover datos de RAM a RAM directamente , no soy un experto en ensamblaje y todo lo que he aprendido sobre el ensamblaje es de este documento ( guía de ensamblaje X86 ) que se menciona en la sección sobre las instrucciones de movimiento que no puede pasar. RAM a RAM. Al parecer esto no es cierto.
Una implementación trivial de memcpy
es:
while (n--) *s2++ = *s1++;
Pero glibc
usualmente usa algunas implementaciones inteligentes en código ensamblador. memcpy
llamadas memcpy
suelen estar en línea.
En x86, el código verifica si el parámetro de tamaño es un múltiplo literal de 2
o un múltiplo de 4
(usando las funciones de gcc
builtins) y usa un bucle con instrucción movl
(copia de 4
bytes), de lo contrario se llama el caso general.
El caso general utiliza el ensamblaje rápido de copia en bloque utilizando las instrucciones de rep
y movsl
.
Depende. En general, no se puede copiar físicamente nada más grande que el registro utilizable más grande en un solo ciclo, pero no es así como funcionan las máquinas en estos días. En la práctica, realmente le importa menos lo que hace la CPU y más las características de la DRAM. La jerarquía de memoria de la máquina desempeñará un papel determinante en la realización de esta copia de la manera más rápida posible (por ejemplo, ¿está cargando líneas de caché completas? ¿Cuál es el tamaño de una fila de DRAM con respecto a la operación de copia?). Una implementación podría optar por utilizar algún tipo de instrucciones vectoriales para implementar memcpy
. Sin referencia a una implementación específica, es efectivamente una copia byte a byte con un búfer de un solo lugar.
Aquí hay un artículo divertido que describe la aventura de una persona para optimizar memcpy
. El principal punto de partida es que siempre se dirigirá a una arquitectura y un entorno específicos según las instrucciones que puede ejecutar de forma económica.