Table of contents
Get information about a process that can run
Check module information of HMI
Check the monitored components
Judging process status UpdateStatus
process
the code
class ProcessMonitor : public RecurrentRunner {
public:
ProcessMonitor();
void RunOnce(const double current_time) override;
private:
static void UpdateStatus(
const std::vector<std::string>& running_processes,
const apollo::dreamview::ProcessMonitorConfig& config,
ComponentStatus* status);
};
void ProcessMonitor::RunOnce(const double current_time) {
// Get running processes.
std::vector<std::string> running_processes;
for (const auto& cmd_file : cyber::common::Glob("/proc/*/cmdline")) {
// Get process command string.
std::string cmd_string;
if (cyber::common::GetContent(cmd_file, &cmd_string) &&
!cmd_string.empty()) {
// In /proc/<PID>/cmdline, the parts are separated with \0, which will be
// converted back to whitespaces here.
std::replace(cmd_string.begin(), cmd_string.end(), '\0', ' ');
running_processes.push_back(cmd_string);
}
}
auto manager = MonitorManager::Instance();
const auto& mode = manager->GetHMIMode();
// Check HMI modules.
auto* hmi_modules = manager->GetStatus()->mutable_hmi_modules();
for (const auto& iter : mode.modules()) {
const std::string& module_name = iter.first;
const auto& config = iter.second.process_monitor_config();
UpdateStatus(running_processes, config, &hmi_modules->at(module_name));
}
// Check monitored components.
auto* components = manager->GetStatus()->mutable_components();
for (const auto& iter : mode.monitored_components()) {
const std::string& name = iter.first;
if (iter.second.has_process() &&
apollo::common::util::ContainsKey(*components, name)) {
const auto& config = iter.second.process();
auto* status = components->at(name).mutable_process_status();
UpdateStatus(running_processes, config, status);
}
}
// Check other components.
auto* other_components = manager->GetStatus()->mutable_other_components();
for (const auto& iter : mode.other_components()) {
const std::string& name = iter.first;
const auto& config = iter.second;
UpdateStatus(running_processes, config, &other_components->at(name));
}
}
analyze
The core processing logic is still in runOnce
Get information about a process that can run
// Get running processes.
std::vector<std::string> running_processes;
for (const auto& cmd_file : cyber::common::Glob("/proc/*/cmdline")) {
// Get process command string.
std::string cmd_string;
if (cyber::common::GetContent(cmd_file, &cmd_string) &&
!cmd_string.empty()) {
// In /proc/<PID>/cmdline, the parts are separated with \0, which will be
// converted back to whitespaces here.
std::replace(cmd_string.begin(), cmd_string.end(), '\0', ' ');
running_processes.push_back(cmd_string);
}
}
First iterate through all the /proc/*/cmdline files. This file describes the process-related information. The * in the middle is the pid. For the specific content of this file, please refer to: https://blog.csdn.net/whatday/article/ details/108897457
The command line parameters of the process can be obtained from the above file, including the startup path of the process (argv[0])
Check module information of HMI
// Check HMI modules.
auto* hmi_modules = manager->GetStatus()->mutable_hmi_modules();
for (const auto& iter : mode.modules()) {
const std::string& module_name = iter.first;
const auto& config = iter.second.process_monitor_config();
UpdateStatus(running_processes, config, &hmi_modules->at(module_name));
}
- Get all HMI configuration modules;
- Check and compare the running process checked in the system with the configured running module, and give the final checking status to &hmi_modules->at(module_name)
Check the monitored components
// Check monitored components.
auto* components = manager->GetStatus()->mutable_components();
for (const auto& iter : mode.monitored_components()) {
const std::string& name = iter.first;
if (iter.second.has_process() &&
apollo::common::util::ContainsKey(*components, name)) {
const auto& config = iter.second.process();
auto* status = components->at(name).mutable_process_status();
UpdateStatus(running_processes, config, status);
}
}
- First get all the components;
- Traverse the components to be monitored and obtain the config information of the process;
- Give to UpdateStatus for final judgment;
Check other components
auto* other_components = manager->GetStatus()->mutable_other_components();
for (const auto& iter : mode.other_components()) {
const std::string& name = iter.first;
const auto& config = iter.second;
UpdateStatus(running_processes, config, &other_components->at(name));
}
}
Same logic as above
Judging process status UpdateStatus
void ProcessMonitor::UpdateStatus(
const std::vector<std::string>& running_processes,
const apollo::dreamview::ProcessMonitorConfig& config,
ComponentStatus* status) {
status->clear_status();
for (const std::string& command : running_processes) {
bool all_keywords_matched = true;
for (const std::string& keyword : config.command_keywords()) {
if (command.find(keyword) == std::string::npos) {
all_keywords_matched = false;
break;
}
}
if (all_keywords_matched) {
// Process command keywords are all matched. The process is running.
SummaryMonitor::EscalateStatus(ComponentStatus::OK, command, status);
return;
}
}
SummaryMonitor::EscalateStatus(ComponentStatus::FATAL, "", status);
}
This is the core judgment function of the entire process monitoring.
- Traverse the running_processes obtained from /proc/*/cmdline before;
- Traverse command_keywords from config, and see if a program name (start position) can be found in running_processes, and the named line parameters can match the item
- true if found, false if not found