Время от времени при разработке приложений в ОС РТ QNX 6.5.0 возникает задача найти процесс, зная только его символическое имя, или узнать некоторую информацию о процессе, или собрать некоторую статистику о процессе.
Это может понадобиться для широкого круга задач.
Эта задача платформенно-специфична и единое кроссплатформенное решение доступно только в виде сторонних библиотек.
В этой статье мы реализуем небольшой класс-обертку, который позволяет нам получать информацию о процессе, зная только его имя.
Мы будем использовать С++.
Для выполнения задачи можно использовать системный вызов «system», вызывая утилиту работы с процессами «pidin», обрабатывая вывод этой утилиты.
Но это решение нас мало интересует. Итак, начнем с того, что в QNX первичной организационной структурой (в отличие, например, от Linux) является поток.
Ядро занимается исключительно планированием потоков.
Процессы — это контейнеры, содержащие один или несколько потоков.
Вся работа с процессами передана менеджеру процессов procnto. Этот менеджер ресурсов создает виртуальный каталог /proc/.
Попробуем отобразить содержимое этого каталога.
Я немного сократил вывод утилиты, чтобы сэкономить место.# ls /proc/ total 41 dr-xr-xr-x 2 root root 1 Sep 04 22:37 1 dr-xr-xr-x 2 root root 1 Sep 04 22:37 110611 dr-xr-xr-x 2 root root 1 Sep 04 22:37 126996 dr-xr-xr-x 2 root root 1 Sep 04 22:37 2 dr-xr-xr-x 2 root root 1 Sep 04 22:37 20489 drwxr-xr-x 2 root root 50 Jul 09 2010 boot nrw------- 1 root root 0 Sep 04 18:15 dumper dr-xr-xr-x 4 root root 1 Sep 04 22:37 self
Вы можете заметить, что выходные данные содержат: 1) каталоги с PID запущенных процессов 2) Виртуальный каталог «boot», в котором хранятся файлы, «скомпилированные» в образ ОС.
3) Файл дампера, используемый утилитой «core dump».
4) Каталог «self» аналогичен каталогам с PID, но предоставляет данные для текущего процесса (в нашем случае ls).
Каталоги с PID содержат один файл с именем «as», который нельзя прочитать или записать с помощью стандартных файловых утилит QNX. Но, с другой стороны, к этим файлам (а по сути и менеджеру procnto) можно получить доступ с помощью системного вызова devctl. Предоставляется полная информация по работе с менеджером procnto. здесь .
Именно это мы и постараемся использовать в разрабатываемом классе.
Как видите, имя отделено от остальной информации devctl. Поэтому мы определим в классе два приватных поля — поле, хранящее имя процесса и системную информацию (системная информация о процессе хранится в структуре типа «debug_process_t»).
Итак, сначала давайте определим публичный интерфейс нашего класса.
Сохраним информацию о конкретном процессе в отдельном классе QNXProcInfo. Поскольку этому классу соответствует один конкретный процесс, вполне логично, что его конструктор будет брать pid процесса (в отличие от имени — pid уникален для каждого процесса, работающего в системе).
Для начала пусть он научится давать нам имя процесса, которому он соответствует, и выводить в поток информацию о себе в текстовом виде.
Тогда заголовок нашего класса будет выглядеть примерно так: class QNXProcInfo
{
public:
QNXProcInfo(int pid);
std::string GetName();
void PrintInfo(std::ostream &out = std::cout);
debug_process_t GetInfo();
private:
std::string* name;
debug_process_t info;
};
Чтобы найти процесс, давайте определим еще один класс QNXProcMgr. Требуется искать процессы по имени и по переданной в компаратор функции.
Заголовок этого класса будет выглядеть примерно так: class QNXProcMgr
{
public:
static QNXProcInfo* Find(std::string pname);
static QNXProcInfo* Find(bool (*comparator)(debug_process_t info));
};
Приступим к реализации.
Для получения информации об имени процесса мы используем пользовательскую структуру имени, содержащую структуру procfs_debuginfo и свободный буфер, в который будет записано имя процесса.
Код будет выглядеть примерно так: QNXProcInfo::QNXProcInfo(int pid)
{
char paths[PATH_MAX];
int fd;
static struct
{
procfs_debuginfo info;
char buff [PATH_MAX];
} name;
sprintf(paths, "/proc/%d/as", pid);
if ((fd = open (paths, O_RDONLY)) == -1)
{
//FIXME: Add error handler here
}
devctl(fd, DCMD_PROC_MAPDEBUG_BASE, &name, sizeof(name), 0);
this->name = new string(name.info.path);
devctl(fd, DCMD_PROC_INFO, &info, sizeof(info), 0);
close (fd);
}
Как видите, для получения имени мы используем команду devctl DCMD_PROC_MAPDEBUG_BASE, при получении которой procnto заполняет переданную ему структуру и записывает имя в буфер пути.
Для получения другой информации используйте команду devctl DCMD_PROC_INFO, при получении которой procnto заполняет информационную структуру, которую мы передаем ему в качестве параметра.
Функции получения имени и отображения информации о процессе выглядят совершенно тривиально и описываться не будут. Стоит только отметить, что информацию о полях структуры debug_process_t можно найти здесь .
Перейдем к рассмотрению функционала класса, отвечающего за поиск процесса.
Вот код, отвечающий за поиск процесса по имени: QNXProcInfo* QNXProcMgr::Find(string pname)
{
struct dirent *dirent;
DIR *dir;
int pid;
string name;
QNXProcInfo *info;
if (!(dir = opendir ("/proc")))
throw QNXProcException("couldn't open /proc");
while ((dirent = readdir(dir)))
{
if (isdigit(*dirent->d_name))
{
pid = atoi(dirent->d_name);
info = new QNXProcInfo(pid);
name = info->GetName();
if (name == pname)
return info;
else delete info;
}
}
closedir (dir);
throw QNXProcException("Process not found");
}
Как видите, используется простой поиск файлов в каталоге /proc, для каждого из найденных файлов (если это PID) создается новый объект ProcInfo, который проверяется на соответствие условию, и если это PID не совпадает, удаляется.
Функция поиска по функции-компаратору выглядит так: QNXProcInfo* QNXProcMgr::Find(bool (*comparator)(debug_process_t info))
{
struct dirent *dirent;
DIR *dir;
int pid;
QNXProcInfo *info;
if (!(dir = opendir ("/proc")))
throw QNXProcException("couldn't open /proc");
while ((dirent = readdir(dir)))
{
if (isdigit(*dirent->d_name))
{
pid = atoi(dirent->d_name);
info = new QNXProcInfo(pid);
if (comparator(info->GetInfo()))
return info;
else delete info;
}
}
closedir (dir);
throw QNXProcException("Process not found");
}
Вот и все.
При необходимости читатель может расширить и дополнить эти занятия в соответствии со своими потребностями.
Также следует отметить, что код не претендует на полноту.
В нем отсутствует обработка некоторых типов ошибок, алгоритм поиска не оптимально структурирован, функция поиска должна уметь возвращать несколько объектов QNXProcInfo (поскольку одному имени могут соответствовать несколько процессов) и многое-многое другое.
Но я уверен, что читатель вполне справится с этим самостоятельно.
Данная статья была призвана лишь показать направление деятельности.
Полные исходники доступны по адресу связь .
Теги: #qnx #neutrino #Системное программирование
-
Посессивность
19 Oct, 24 -
Myspace Дублирует Функциональность Youtube
19 Oct, 24