2015-07-30 3 views
1

Я запускаю Ubuntu, и я не понимаю, почему мне так сложно получить количество ядер в моей системе на C! Я пробовал синтаксический анализ /proc/cpuinfo с успехом в моей системе, работающей под управлением Ubuntu, но затем я попытался использовать еще одну систему, в которой работает arch linux, которая завершилась неудачно, потому что буфер был слишком мал, и я не могу понять, как заставить его работать на обоих мои системы.Как разобрать/proc/cpuinfo на любом дистрибутиве linux в C

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    FILE* fp; 
    char *buffer, *tmp; 
    size_t bytes_read, size; 

    if((fp = fopen("/proc/cpuinfo", "r")) == NULL) { 
    perror("open failed"); 
    exit(EXIT_FAILURE); 
    } 
    size = 1024; 
    if((buffer = malloc(size)) == NULL) { 
    perror("malloc failed"); 
    free(buffer); 
    exit(EXIT_FAILURE); 
    } 
    while(!feof(fp)) { 
    bytes_read = fread(buffer, 1, size, fp); 
    if(bytes_read == size) { 
     size += 128; 
     if((tmp = realloc(buffer, size)) == NULL) { 
     perror("realloc failed"); 
     free(buffer); 
     exit(EXIT_FAILURE); 
     }else { 
     buffer = tmp; 
     } 
    } 
    } 
    fclose(fp); 
    if(bytes_read == 0 || bytes_read == size) { 
    perror("read failed or buffer isn't big enough."); 
    exit(EXIT_FAILURE); 
    } 
    printf("%d bytes read out of %d\n", (int)bytes_read,(int) size); 
    buffer[bytes_read] = '\0'; 

    printf("%s", buffer); 
} 

Это выводит 572 bytes read out of 1152, но он перезаписывает буфер всякий раз, когда я снова использовать fread. И я не могу использовать sysconf(_SC_NPROCESSORS_ONLN);, потому что он не работает на Ubuntu.

+3

Не делайте 'while (! Feof (...))', он будет работать редко, как вы ожидаете. Причина в том, что флаг конца файла не установлен до тех пор, пока вы не попробуете прочитать из-за конца файла в первый раз. Это приводит к тому, что ваш цикл повторяется один раз для многих, без особого внимания. –

+3

Во-вторых, использование 'sizeof' на указателе возвращает размер * указателя *, а не то, на что указывает. –

+0

@JoachimPileborg Но 'ftell' не работает с'/proc/cpuinfo', так как я не могу открыть его в двоичном режиме, возможно, потому, что он думает, что я хочу выполнить файл. – Linus

ответ

2

Как с помощью popen(3) выполнить cat ^processor /proc/cpuinfo | wc -l, чтобы получить количество процессоров, а затем прочитать результат из трубы? Это довольно просто, и вам не придется поддерживать сложный код для чтения и анализа всего файла.

Вот пример:

#include <stdio.h> 

int ncpus(void) { 
    FILE *cmd = popen("grep '^processor' /proc/cpuinfo | wc -l", "r"); 

    if (cmd == NULL) 
     return -1; 

    unsigned nprocs; 
    size_t n; 
    char buff[8]; 

    if ((n = fread(buff, 1, sizeof(buff)-1, cmd)) <= 0) 
     return -1; 

    buff[n] = '\0'; 
    if (sscanf(buff, "%u", &nprocs) != 1) 
     return -1; 

    pclose(cmd); 

    return nprocs; 
} 

int main(void) { 
    int cpus = ncpus(); 
    if (cpus == -1) 
     fprintf(stderr, "Error retrieving number of CPUs\n"); 
    else 
     printf("Number of CPUs: %d\n", cpus); 
    return 0; 
} 

Вы можете улучшить обработку в ncpus() ошибку, чтобы быть немного удобно (прямо сейчас, вы на самом деле не знаю, что случилось, если, если возвращается -1) ,

UPDATE

Как упомянуто ниже в комментариях, nproc(1) может быть лучшим выбором здесь, по крайней мере, команда меньше. Он будет работать в любом случае, мы можем просто заменить grep + wc на nproc.

+0

Это классный способ сделать это, однако лучше использовать nproc? Я имею в виду, что это, конечно, менее сложно. – Linus

+0

@Linus Ah y ээ, абсолютно! Вы можете определенно использовать 'nproc (1)' вместо 'grep' +' wc'. Я не думал об этом. Он должен работать, если вы просто измените команду, переданную 'popen (3)', так как обе команды имеют одинаковый вывод. Обновил мой ответ (и подтвердил, что он работает в обоих направлениях). –

 Смежные вопросы

  • Нет связанных вопросов^_^