#c #linux #process #popen #pid
#c #linux #процесс #popen #pid
Вопрос:
В Linux я нахожу pid процесса, открывая канал с помощью команды «pidof process_name», а затем считываю его вывод с помощью функции fgets. Но время от времени не удается найти pid. Ниже приведен мой код для поиска pid моего процесса.
int FindPidByProcessName(char *pName)
{
int pid = -1;
char line[30] = { 0 };
char buf[64] = { 0 };
sprintf(buf, "pidof %s", pName);
//pipe stream to process
FILE *cmd = popen(buf, "r");
if (NULL != cmd)
{
//get line from pipe stream
fgets(line, 30, cmd);
//close pipe
pclose(cmd); cmd = NULL;
//convert string to unsigned LONG integer
pid = strtoul(line, NULL, 10);
}
return pid;
}
На выходе иногда появляется pid = 0, даже если процесс доступен в выводе команды «ps».
Итак, я пытаюсь найти основную причину этой проблемы, и я обнаружил, что что-то вроде механизма буфера ввода / вывода может создать проблему в моем сценарии.
Поэтому я пытаюсь использовать функцию sync () перед открытием popen(), и, как ни странно, моя функция начинает работать со 100% точностью.
Теперь функция sync () занимает слишком много времени (примерно 2 минуты) для завершения ее выполнения, что нежелательно. Поэтому я пытаюсь использовать fflush(), fsync() и fdatasync (), но все они не работают должным образом.
Итак, пожалуйста, кто-нибудь скажет мне, какова была точная первопричина этой проблемы и как решить эту проблему надлежащим образом?
Комментарии:
1. Я не понимаю вашего
while
цикла — вы вызываете толькоpopen
один раз, почему вы зацикливаетесь при чтении вывода?2. Извините за недопонимание, это просто формат кодирования, который я использую для написания функций. Здесь это не имеет значения, поскольку это while(0). Это не будет зациклено.
3. Когда
pid
есть0
, каково содержимоеline
?4. линейная переменная пуста. Видите, что это работает 100 раз, но почему-то это не работает, вы можете сказать, что раз в 100 раз это терпит неудачу.
5. Добавьте какой-нибудь код, который выполняется,
perror
еслиfgets
возвращается значение null, и сообщите нам, что это за сообщение об ошибке.
Ответ №1:
Хорошо, основная причина ошибки хранится в переменной errno (которую, кстати, вам не нужно инициализировать). Вы можете получить информативное сообщение с помощью функции
perror("Error: ");
Если вы используете perror, интерпретируется переменная errno, и вы получаете описательное сообщение.
Другой способ (правильный способ!) найти первопричину — это скомпилировать вашу программу с флагом -g и запустить двоичный файл с помощью gdb.
Редактировать: я настоятельно рекомендую использовать отладчик gdb, чтобы вы могли точно посмотреть, по какому пути следует ваш код, чтобы вы могли объяснить описанное вами странное поведение.
Второе редактирование: Errno сохраняет последнюю ошибку (возвращаемое значение). Вместо того, чтобы вызывать функции, как вы это делаете, вы должны немедленно написать и проверить errno:
if ((<function>) <0) {
perror("<function>: ");
exit(1);
}
Комментарии:
1. Я ценю ваши мысли. Но я уже выполнял отладку с помощью gdb, чтобы найти основную причину. Здесь дело в том, что в fgets() не выводится вывод при попытке прочитать ФАЙЛ *. Итак, это моя проблема с некоторым механизмом буфера ввода-вывода.
2. @ravibhuva9955 что возвращает fgets()? Вы можете использовать команду strace для мониторинга системных вызовов ваших программ (включая операции ввода-вывода).
3. в этом случае fgets возвращает NULL.
4. Хорошо, один случай (из всех других ошибок), когда fgets возвращает null, — это когда это EOF. Можете ли вы подтвердить, что это не так? Потому что, если это EOF (нечего читать в канале), это нормальное поведение