1 /* 2 SPDX-FileCopyrightText: 2007 John Tapsell <tapsell@kde.org> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5 */ 6 7 #ifndef PROCESSES_H_ 8 #define PROCESSES_H_ 9 10 #include "process.h" 11 #include <QHash> 12 #include <QObject> 13 #include <QVariant> 14 15 namespace KSysGuard 16 { 17 /** 18 * This class retrieves the processes currently running in an OS independent way. 19 * 20 * To use, do something like: 21 * 22 * \code 23 * #include "processes.h> 24 * #include "process.h> 25 * 26 * KSysGuard::Processes *processes = new KSysGuard::Processes() 27 * QHash<long, Process *> processlist = processes->getProcesses(); 28 * foreach( Process * process, processlist) { 29 * kDebug() << "Process with pid " << process->pid() << " is called " << process->name; 30 * } 31 * delete processes; 32 * processes = NULL; 33 * \endcode 34 * 35 * @author John Tapsell <tapsell@kde.org> 36 */ 37 #ifdef Q_WS_WIN 38 class Processes : public QObject 39 #else 40 class Q_DECL_EXPORT Processes : public QObject 41 #endif 42 { 43 Q_OBJECT 44 45 public: 46 Processes(const QString &hostname = QString(), QObject *parent = nullptr); 47 ~Processes() override; 48 enum UpdateFlag { 49 StandardInformation = 1, 50 IOStatistics = 2, 51 XMemory = 4, 52 Smaps = 8, 53 }; 54 Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag) 55 56 enum Error { Unknown = 0, InvalidPid, InvalidParameter, InsufficientPermissions, ProcessDoesNotExistOrZombie, NotSupported, NoError }; 57 58 /** 59 * Update all the process information. After calling this, /proc or equivalent is scanned and 60 * the signals processChanged, etc are emitted. 61 * 62 * Set updateDuration to whatever time period that you update, in milliseconds. 63 * For example, if you update every 2000ms, set this to 2000. That way it won't update 64 * more often than needed. 65 */ 66 void updateAllProcesses(long updateDurationMS = 0, Processes::UpdateFlags updateFlags = {}); 67 68 /** 69 * Return information for one specific process. Call getProcess(0) to get the 70 * fake process used as the top most parent for all processes. 71 * This doesn't fetch any new information and so returns almost instantly. 72 * Call updateAllProcesses() to actually fetch the process information. 73 */ 74 Process *getProcess(long pid) const; 75 76 /** 77 * Get the error code for the last command that failed. 78 */ 79 Error lastError() const; 80 81 /** 82 * Kill the specified process. You may not have the privilege to kill the process. 83 * The process may also chose to ignore the command. Send the SIGKILL signal to kill 84 * the process immediately. You may lose any unsaved data. 85 * 86 * @returns Successful or not in killing the process 87 */ 88 bool killProcess(long pid); 89 90 /** 91 * Send the specified named POSIX signal to the process given. 92 * 93 * For example, to indicate for process 324 to STOP do: 94 * \code 95 * #include <signals.h> 96 * ... 97 * 98 * KSysGuard::Processes::sendSignal(23, SIGSTOP); 99 * \endcode 100 * 101 */ 102 bool sendSignal(long pid, int sig); 103 104 /** 105 * Set the priority for a process. This is from 19 (very nice, lowest priority) to 106 * -20 (highest priority). The default value for a process is 0. 107 * 108 * @return false if you do not have permission to set the priority 109 */ 110 bool setNiceness(long pid, int priority); 111 112 /** 113 * Set the scheduler for a process. This is defined according to POSIX.1-2001 114 * See "man sched_setscheduler" for more information. 115 * 116 * @p priorityClass One of SCHED_FIFO, SCHED_RR, SCHED_OTHER, and SCHED_BATCH 117 * @p priority Set to 0 for SCHED_OTHER and SCHED_BATCH. Between 1 and 99 for SCHED_FIFO and SCHED_RR 118 * @return false if you do not have permission to set the priority 119 */ 120 bool setScheduler(long pid, KSysGuard::Process::Scheduler priorityClass, int priority); 121 122 /** 123 * Set the io priority for a process. This is from 7 (very nice, lowest io priority) to 124 * 0 (highest priority). The default value is determined as: io_nice = (cpu_nice + 20) / 5. 125 * 126 * @return false if you do not have permission to set the priority 127 */ 128 bool setIoNiceness(long pid, KSysGuard::Process::IoPriorityClass priorityClass, int priority); 129 130 /** 131 * Returns true if ionice is supported on this system 132 */ 133 bool supportsIoNiceness(); 134 135 /** 136 * Return the internal pointer of all the processes. The order of the processes 137 * is guaranteed to never change. Call updateAllProcesses() first to actually 138 * update the information. 139 */ 140 const QList<Process *> &getAllProcesses() const; 141 142 /** 143 * Return the number of processes. Call updateAllProcesses() to actually 144 * update the information. 145 * 146 * This is equivalent to getAllProcesses().count() 147 */ 148 int processCount() const; 149 150 /** 151 * Return the total amount of physical memory in KB. This is fast (just a system call) 152 * Returns 0 on error 153 */ 154 long long totalPhysicalMemory(); 155 156 /** 157 * Return the number of processor cores enabled. 158 * (A system can disable processors. Disabled processors are not counted here). 159 * This is fast (just a system call) */ 160 long numberProcessorCores(); 161 162 /** Update/add process for given pid immediately */ 163 bool updateOrAddProcess(long pid); 164 165 /** Whether we can get historic process and system data */ 166 bool isHistoryAvailable() const; 167 168 /** Stop using historical data and use the most recent up-to-date data */ 169 void useCurrentData(); 170 171 /** Return a list of end times and intervals for all the available history */ 172 QList<QPair<QDateTime, uint>> historiesAvailable() const; 173 174 /** Use historical process data closest to the given date-time. 175 * Returns false if it is outside the range available or there is a problem 176 * getting the data. */ 177 bool setViewingTime(const QDateTime &when); 178 QDateTime viewingTime() const; 179 bool loadHistoryFile(const QString &filename); 180 QString historyFileName() const; 181 182 public Q_SLOTS: 183 /** The abstract processes has updated its list of processes */ 184 void processesUpdated(); 185 void processUpdated(long pid, const Process::Updates &changes); 186 187 Q_SIGNALS: 188 /** The data for a process has changed. 189 * if @p onlyTotalCpu is set, only the total cpu usage has been updated. 190 * process->changes contains a bit field indicating what has changed since the last time this was emitted 191 * for this process 192 */ 193 void processChanged(KSysGuard::Process *process, bool onlyTotalCpu); 194 195 /** 196 * This indicates we are about to add a process in the model. 197 * The process already has the pid, ppid and tree_parent set up. 198 */ 199 void beginAddProcess(KSysGuard::Process *process); 200 201 /** 202 * We have finished inserting a process 203 */ 204 void endAddProcess(); 205 /** 206 * This indicates we are about to remove a process in the model. Emit the appropriate signals 207 */ 208 209 void beginRemoveProcess(KSysGuard::Process *process); 210 211 /** 212 * We have finished removing a process 213 */ 214 void endRemoveProcess(); 215 216 /** 217 * This indicates we are about move a process from one parent to another. 218 */ 219 void beginMoveProcess(KSysGuard::Process *process, KSysGuard::Process *new_parent); 220 221 /** 222 * We have finished moving the process 223 */ 224 void endMoveProcess(); 225 226 void updated(); 227 228 protected: 229 class Private; 230 Private *d; 231 232 private: 233 inline void deleteProcess(long pid); 234 bool updateProcess(Process *process, long ppid); 235 bool updateProcessInfo(Process *ps); 236 bool addProcess(long pid, long ppid); 237 238 Q_SIGNALS: 239 /** For a remote machine, we rely on being able to communicate with ksysguardd. 240 * This must be dealt with by the program including this widget. It must listen to our 241 * 'runCommand' signal, and run the given command, with the given id. */ 242 void runCommand(const QString &command, int id); 243 244 public: 245 /** For a remote machine, we rely on being able to communicate with ksysguardd. 246 * The programming using this must call this slot when an answer is received from ksysguardd, 247 * in response to a runCommand request. The id identifies the answer */ 248 void answerReceived(int id, const QList<QByteArray> &answer); 249 }; 250 Q_DECLARE_OPERATORS_FOR_FLAGS(Processes::UpdateFlags) 251 } 252 253 #endif 254