Чтение информации о proc stat

Здравствуйте, мне нужна следующая информация о процессе с некоторым PID:

имя, ppid, состояние, #ofOpenFiles, #ofThreads

Я знаю, что пример файла /proc/pid/stat выглядит так:

15 (Watchdog / 1) S 2 0 0 0 -1 69239104 0 0 0 0 0 69 0 0-100 0 1 0 6 0 0 18446744073709551615 0 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 1 99 1 0 0 0 0 0 0 0 0 0 0 0

Моя текущая попытка разбора такого файла:

FILE *fp;
           char buff[255];
           fp= fopen("/proc/123/stat", "r");
           if(fp == NULL){

           }else{

             fscanf(fp, "%d %s %c %d %d %d %d %d %u %lu ....", &pid, &name, &ppid......)
             fclose(fp);
           }

Я не нахожу этот метод очень хорошим. Как это сделать?


person Jonzi    schedule 03.01.2016    source источник
comment
Что конкретно вам не нравится в вашем нынешнем методе чтения /proc?   -  person kaylum    schedule 03.01.2016
comment
похоже, я собираю много информации, которая мне не нужна. Значит есть лучший способ :s?   -  person Jonzi    schedule 03.01.2016
comment
1. Вам не нужно читать весь файл stat. Просто остановитесь на последнем интересующем вас поле. 2. Для любых полей, которые вам нужно прочитать, но которые вам не нужны, используйте спецификатор формата *, чтобы игнорировать его, чтобы вам не нужно было указывать переменную для хранения. его значение.   -  person kaylum    schedule 03.01.2016
comment
спасибо @kaylum, это мне немного помогло :)   -  person Jonzi    schedule 03.01.2016
comment
Является ли C требованием? В противном случае простой awk-скрипт был бы намного проще.   -  person Matthieu    schedule 03.01.2016
comment
@Матье, да, к сожалению   -  person Jonzi    schedule 03.01.2016
comment
@Jonzi жаль это слышать;) зная, что /proc/stat предназначен только для Linux, а Linux обычно поставляется с awk ...   -  person Matthieu    schedule 03.01.2016
comment
получил это работает. спасибо вам обоим. Кайлум Матье   -  person Jonzi    schedule 03.01.2016
comment
Обратите внимание, что есть проблема, поскольку имя файла (вторая запись) может содержать пробелы и не обязательно должно содержать (, поэтому синтаксический анализ немного сложнее.   -  person Nemanja Boric    schedule 24.01.2017
comment
Извините, я неправильно прочитал справочную страницу - скобки всегда там.   -  person Nemanja Boric    schedule 24.01.2017
comment
@Jonzi - Вы знаете, как часто /proc/stat/ обновляется с новым временем?   -  person Chetan Arvind Patil    schedule 10.04.2018
comment
@ChetanArvindPatil почти уверен, что он будет доступен в любой момент   -  person Jonzi    schedule 10.04.2018
comment
@Jonzi - Нет определенного интервала обновления в msec()?   -  person Chetan Arvind Patil    schedule 10.04.2018
comment
@ChetanArvindPatil Быстрый поиск в Google даст вам всю необходимую информацию.   -  person Jonzi    schedule 11.04.2018


Ответы (1)


Описанное вами решение выглядит хорошо (особенно с использованием идеи @kaylum о спецификаторе формата *). Обратите внимание, что вы можете использовать одну и ту же переменную несколько раз, чтобы игнорировать параметры:

fscanf(fp, "%d %s %c %d %d %d %d %d %u %lu ...", &pid, &name, &ppid, &dummy, &dummy, &dummy, ...);

Вы также можете заглянуть в strtok, чтобы прочитать "токен" каждой строки, токен. Вы можете использовать его для создания функции, возвращающей массив char*, как в этот другой вопрос и получить i-й элемент (со всеми правильными проверками NULL и размера).

Изменить: если имя файла содержит пробелы, вам придется либо использовать регулярное выражение, либо проанализировать строку вручную, например. strtok() для определения правильного формата.

person Matthieu    schedule 03.01.2016
comment
Что произойдет, если стат файл выглядит следующим образом: 49102 (Имя с пространством) S 3249 3506 3506 0 -1 1077936192 573 0 0 0 671 575 0 0 20 0 11 0 10835724 808615936 13699 18446744073709551615 4194304 8101684 140732335739408 140538183277872 140538250385161 0 4 4096 1260 1 0 0 -1 7 0 0 0 0 0 10201672 10213228 40337408 140732335748225 140732335748579 140732335748579 140732335751059 0 Здесь имя будет неверным (Имя и следующее чтение fscanf. - person txs; 19.09.2018
comment
@txs, тогда это не сработает. Вам придется прибегнуть к регулярному выражению или ручному разбору. Я отредактировал, чтобы было понятнее. Будет ли этого достаточно, чтобы убрать минус? - person Matthieu; 19.09.2018
comment
@txs, в этом случае вам нужно сделать что-то вроде этого: "%*s (%*16[^)]) %s". В этом случае мне не нужно первое значение и второе значение, мне нужно только третье значение в виде строки. Если они вам нужны, просто удалите * и назначьте правильные переменные... - person S.Goswami; 31.01.2021
comment
Также обратите внимание, что сама строка может содержать более 16 символов, если это процесс ядра. Процесс также может быть обернут внутри () без каких-либо `, like (sd-pam)`, например. Итак, вам нужно сопоставить все рекурсивные ). Это работает: fscanf(f, "%*llu (%*[^)]%*[)] %c", _s) ; Опять же, это игнорирует, например, первые 2 значения. Вы не можете достоверно сказать длину второго поля, потому что она не ограничена TASK_COMM_LEN для космических программ ядра. - person S.Goswami; 01.02.2021