2009-05-12 19 views
6

Mi aplicación que se ejecuta en Mac OS X necesita recuperar los detalles sobre la máquina en la que se está ejecutando para generar informes de información del sistema. Uno de los elementos que necesito es detalles sobre los procesadores instalados en la computadora.Obtenga detalles del procesador mediante programación desde Mac OS X

Mi código funciona actualmente, pero está lejos de ser una solución ideal, de hecho la considero una mala solución, pero no he tenido suerte para encontrar una mejor.

La información que yo actualmente y después de algún formato será similar a:

Procesador: Intel Core 2 Duo a 2,1 GHz, Familia 6 Modelo 23 Stepping 6

Toda la información que recibo es a través de utilidades de línea de comandos llamadas desde un popen(). La parte legible de la descripción del procesador se toma de la salida del comando "system_profiler" y los valores de Familia, Modelo y Stepping se toman del comando "sysctl".

Estas utilidades de línea de comandos deben obtener información de algún lugar. Me pregunto si hay una interfaz programática disponible para obtener esta misma información.


relacionadas:

+0

Si alguien tiene la respuesta, probablemente debería agregarse al enlace "relacionado" también ... – dmckee

Respuesta

5

sysctl(3) es probablemente un buen lugar para comenzar. Probablemente desee las cosas definidas por los selectores CTL_HW.

+0

Recuerdo que miré el método sysctl() con el selector CTL_HW que mencionas, pero no parece proporcionar los valores enteros Family, Model y Stepping que estoy obteniendo ahora, y creo que solo proporciona una descripción del procesador de tipo x86 muy genérica. Sin embargo, el sysctlbyname() podría tener mejor suerte. No estoy seguro de si alguna vez lo estudié de cerca. Investigaré e informaré mis hallazgos. ¡Gracias! – brader24

+0

Puede usar syscctlnametomib para extraer los números de familia, modelo y escalonamiento que puede usar para sysctl. Es aproximadamente 3 veces más rápido que sysctlbyname. –

7

Debe mirar las API de IOKit. La aplicación IORegistryExplorer (parte de la instalación estándar de devtools) lo ayudará a encontrar lo que está buscando.

Por ejemplo, en mi MacBook Pro, en IORegistryExplorer selecciono 'IODeviceTree' desde el menú desplegable en la parte superior izquierda de la ventana, y puedo ver dos CPU en la vista de árbol a continuación. Al seleccionar cualquiera de los dos me pone la siguiente información:

IORegistryExplorer screenshot http://blog.alanquatermain.net/images/IORegistryExplorer-CPUs.png

'bus-frecuencia' y 'reloj de frecuencia' y 'base de tiempo-frecuencia' son todos los números enteros de 32 bits envoltorio de objetos de datos, y por lo tanto debe intercambiarse bytes de interpretar aquí (palabras máquina i386 little-endian), y trabajar con los siguientes valores:

  • bus de frecuencia: 1064000000 Hz => 1,064 GHz
  • reloj de frecuencia: 2530000000 Hz = > 2.53 GHz
  • base de tiempo-frecuencia: 1000000000 HZ => 1.0 GHz

Si estás leyendo esto a través de IOKit sin embargo, tendrá que volver una CFDataRef, y simplemente copiar los bytes en su propio uint32_t así:

uint32_t bus_frequency = 0; 
CFDataGetBytes(theData, (UInt8 *) &bus_frequency, sizeof(uint32_t)); 

A continuación, se puede obtener información sobre el procesador en la llamada NXArchInfo() obtenido mediante la inclusión de <mach-o/arch.h>. Esto devolverá una estructura que contiene el tipo de CPU y los códigos de subtipo junto con los nombres y descripciones de la cadena C.Si eso no incluye una identificación escalonada, la única forma en que puedo pensar para obtener eso (fuera de lo común) es a través de la instrucción CPUID. Crear un archivo .h y .s, y poner en el siguiente código:

archivo .s:

#ifdef __i386__ || __x86_64__ 

.macro ENTRY 
    .text 
    .private_extern $0 
    .align 4, 0x90 
$0: 
.endmacro 

// __private_extern__ unsigned long GetCPUSteppingID(void) 
ENTRY _GetCPUSteppingID 
    push  %ebp    // store existing frame pointer 
    mov   %esp,%ebp   // make a new frame pointer from stack pointer 
#if __x86_64__ 
    push  %rbx 
#endif 
    push  %ebx    // we save %ebx because the cpuid instruction 
            // will overwrite it, and it's expected 
            // to be unchanged in the caller after 
            // calling another function 
    movl  $1,%eax    // fetch cpu info 
    cpuid       // stepping-id is in low 4 bits of %edx now 
    and   $0x0000000f,%edx // clear out everything we don't want 
#if __x86_64__ 
    mov   %edx,%rax   // %rax is 64-bit arch result register 
#else 
    mov   %edx,%eax   // %eax is 32-bit arch result register 
#endif 
    pop   %ebx    // restore saved value of %ebx 
#if __x86_64__ 
    pop   %rbx    // restore saved value of %rbx 
#endif 
    leave       // restores prior stack frame from %ebp 
    ret        // returns to caller 

#endif // __i386__ || __x86_64__ 

archivo .h:

#ifndef __GET_STEPPING_ID__ 
#define __GET_STEPPING_ID__ 

/* unsigned long is register-sized on both 32-bit and 64-bit OS X */ 
__private_extern__ unsigned long GetSteppingID(void); 

#endif /* __GET_STEPPING_ID__ */ 

Tenga en cuenta que no estoy seguro aproximadamente el bit x86_64 anterior; en teoría, lo que he escrito allí asegurará que el mismo código se compile para 64 bits, y devolverá un valor de 64 bits en ese caso. También guardará/restaurará el registro% rbx, la versión de 64 bits del registro% ebx. Teóricamente que cubrirá todas las bases.

0

Si desea específicamente la información de la CPU, utilice la instrucción cpuid (en C __asm ​​cpuid). Proporciona toda la información posible de una CPU, incluida su familia, modelo, empresa, número de núcleos, etc. Principalmente todas las API utilizan esta instrucción para recuperar información de la CPU. Puede obtener información detallada sobre CPUID en la web, incluido el código de muestra y tutoriales.

6

Use sysctlbyname en lugar de sysctl, p.

#include <stdio.h> 
#include <stdint.h> 
#include <sys/types.h> 
#include <sys/sysctl.h> 

uint64_t get_cpu_freq(void) 
{ 
    uint64_t freq = 0; 
    size_t size = sizeof(freq); 

    if (sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0) < 0) 
    { 
     perror("sysctl"); 
    } 
    return freq; 
} 

Usted puede obtener una lista de los nombres que se pueden pasar a systctlbyname observando la salida del sysctl -a desde la línea de comandos.

Cuestiones relacionadas