📜 ⬆️ ⬇️

Programmatic process lookup by name in QNX 6.5.0

Periodically, when developing applications in QNX OS 6.5 QNX OS, the problem arises to find the process knowing only its symbolic name, or find out any information about the process, or collect some statistics about the process. This may be needed for a wide range of tasks.

image

This task is platform-specific and a single cross-platform solution is available only in the form of third-party libraries.
')
In this article, we are implementing a small “wrapper” class that allows you to get information about the process, knowing only its name. We will use YaP C ++.

To perform the task, you can use the system call “system”, calling the utility for working with the processes “pidin”, processing the output of this utility. But, this decision interests us a little.

So let's start with the fact that in QNX the primary organizational structure (as opposed to, for example, Linux) is the flow. The kernel deals exclusively with the layout of threads. Processes are containers containing one or more threads. All work with the processes submitted to the process manager procnto.

This resource manager creates a virtual directory / proc /. Let's try to display the contents of this directory.

# 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 

I have slightly reduced the output of the utility, to save space. You may notice that there are in the output:

1) PID directories of running processes
2) Virtual directory "boot", which stores the files "compiled" in the OS image.
3) The dumper file used by the core dump utility
4) The “self” directory is similar to directories with a PID, but provides data for the current process (in our case ls).

In directories with a PID, there is a single file called “as” that cannot be read or written by regular QNX utilities working with files. But, on the other hand, these files (in fact, the procnto manager) can be accessed using the devctl system call. Full details of working with the procnto manager are presented here .

We will try to use this in the class we are developing. As you can see, the name is obtained separately from the rest of the devctl information. Therefore, we define two private fields in the class - a field that stores the process name and system information (system information about the process is stored in a structure of the type “debug_process_t”).

So, for the beginning we will define the public interface of our class. Let us have information about a specific process stored in a separate class QNXProcInfo. Since this class corresponds to one specific process, it is quite logical that its constructor takes in the pid of the process (unlike the name, pid is unique for each process launched in the system). To begin, let him learn to give us the name of the process to which he corresponds and print out in a text form the flow of information about himself.

Then the heading of our class will look something like this:

  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; }; 

To search for a process, we define another class QNXProcMgr. It is required to search for processes by name and by the transferred function to the comparator.

The title of this class will look something like this:

  class QNXProcMgr { public: static QNXProcInfo* Find(std::string pname); static QNXProcInfo* Find(bool (*comparator)(debug_process_t info)); }; 

We proceed to the implementation.

To obtain information about the process name, we use a custom name structure, which contains the procfs_debuginfo structure and a free buffer in which the process name will be written.

The code will look something like this:

 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); } 

As you can see, to get the name, we use the devctl command DCMD_PROC_MAPDEBUG_BASE, upon receipt of which the procnto fills the structure passed to it and writes the name to the path buffer.

For other information, the devctl command DCMD_PROC_INFO is used, upon receipt of which the procnto fills in the info structure, which we pass to it as a parameter.

The functions of receiving the name and displaying information about the process look quite trivial and will not be described. It is only necessary to note that information about the fields of the structure debug_process_t can be found here .

Let us consider the functionality of the class responsible for finding the process.

Here is the code responsible for finding the process by name:

  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"); } 

As you can see, a simple search of files in the / proc directory is used, for each of the found files (if it is a PID), a new ProcInfo object is created, which is checked for compliance with the condition, and is deleted if it is not.

It looks like the function to search for the comparator function:

 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"); } 

That's all. If necessary, the reader can expand and supplement the specified classes in accordance with their needs.

Also, it should be noted that the code does not claim to be complete. It does not handle some types of errors, the search algorithm is not optimally built, the search function should be able to give several QNXProcInfo objects (since several processes can correspond to one name) and much more. But, I am sure that the reader will cope with it completely. This article was intended only to show the direction of activity.

Full source code available on the link .

Source: https://habr.com/ru/post/279509/


All Articles