File indexing completed on 2024-04-28 05:31:38
0001 /* 0002 SPDX-FileCopyrightText: 2007 John Tapsell <tapsell@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef PROCESSES_H_ 0008 #define PROCESSES_H_ 0009 0010 #include "process.h" 0011 #include <QHash> 0012 #include <QObject> 0013 #include <QVariant> 0014 0015 #include "processcore_export.h" 0016 0017 namespace KSysGuard 0018 { 0019 /** 0020 * This class retrieves the processes currently running in an OS independent way. 0021 * 0022 * To use, do something like: 0023 * 0024 * \code 0025 * #include "processes.h> 0026 * #include "process.h> 0027 * 0028 * KSysGuard::Processes *processes = new KSysGuard::Processes() 0029 * QHash<long, Process *> processlist = processes->getProcesses(); 0030 * foreach( Process * process, processlist) { 0031 * kDebug() << "Process with pid " << process->pid() << " is called " << process->name; 0032 * } 0033 * delete processes; 0034 * processes = NULL; 0035 * \endcode 0036 * 0037 * @author John Tapsell <tapsell@kde.org> 0038 */ 0039 #ifdef Q_WS_WIN 0040 class Processes : public QObject 0041 #else 0042 class PROCESSCORE_EXPORT Processes : public QObject 0043 #endif 0044 { 0045 Q_OBJECT 0046 0047 public: 0048 Processes(const QString &hostname = QString(), QObject *parent = nullptr); 0049 ~Processes() override; 0050 enum UpdateFlag { 0051 StandardInformation = 1, 0052 IOStatistics = 2, 0053 XMemory = 4, 0054 Smaps = 8, 0055 }; 0056 Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag) 0057 0058 enum Error { Unknown = 0, InvalidPid, InvalidParameter, InsufficientPermissions, ProcessDoesNotExistOrZombie, NotSupported, NoError }; 0059 0060 /** 0061 * Update all the process information. After calling this, /proc or equivalent is scanned and 0062 * the signals processChanged, etc are emitted. 0063 * 0064 * Set updateDuration to whatever time period that you update, in milliseconds. 0065 * For example, if you update every 2000ms, set this to 2000. That way it won't update 0066 * more often than needed. 0067 */ 0068 void updateAllProcesses(long updateDurationMS = 0, Processes::UpdateFlags updateFlags = {}); 0069 0070 /** 0071 * Return information for one specific process. Call getProcess(0) to get the 0072 * fake process used as the top most parent for all processes. 0073 * This doesn't fetch any new information and so returns almost instantly. 0074 * Call updateAllProcesses() to actually fetch the process information. 0075 */ 0076 Process *getProcess(long pid) const; 0077 0078 /** 0079 * Get the error code for the last command that failed. 0080 */ 0081 Error lastError() const; 0082 0083 /** 0084 * Kill the specified process. You may not have the privilege to kill the process. 0085 * The process may also chose to ignore the command. Send the SIGKILL signal to kill 0086 * the process immediately. You may lose any unsaved data. 0087 * 0088 * @returns Successful or not in killing the process 0089 */ 0090 bool killProcess(long pid); 0091 0092 /** 0093 * Send the specified named POSIX signal to the process given. 0094 * 0095 * For example, to indicate for process 324 to STOP do: 0096 * \code 0097 * #include <signals.h> 0098 * ... 0099 * 0100 * KSysGuard::Processes::sendSignal(23, SIGSTOP); 0101 * \endcode 0102 * 0103 */ 0104 bool sendSignal(long pid, int sig); 0105 0106 /** 0107 * Set the priority for a process. This is from 19 (very nice, lowest priority) to 0108 * -20 (highest priority). The default value for a process is 0. 0109 * 0110 * @return false if you do not have permission to set the priority 0111 */ 0112 bool setNiceness(long pid, int priority); 0113 0114 /** 0115 * Set the scheduler for a process. This is defined according to POSIX.1-2001 0116 * See "man sched_setscheduler" for more information. 0117 * 0118 * @p priorityClass One of SCHED_FIFO, SCHED_RR, SCHED_OTHER, and SCHED_BATCH 0119 * @p priority Set to 0 for SCHED_OTHER and SCHED_BATCH. Between 1 and 99 for SCHED_FIFO and SCHED_RR 0120 * @return false if you do not have permission to set the priority 0121 */ 0122 bool setScheduler(long pid, KSysGuard::Process::Scheduler priorityClass, int priority); 0123 0124 /** 0125 * Set the io priority for a process. This is from 7 (very nice, lowest io priority) to 0126 * 0 (highest priority). The default value is determined as: io_nice = (cpu_nice + 20) / 5. 0127 * 0128 * @return false if you do not have permission to set the priority 0129 */ 0130 bool setIoNiceness(long pid, KSysGuard::Process::IoPriorityClass priorityClass, int priority); 0131 0132 /** 0133 * Returns true if ionice is supported on this system 0134 */ 0135 bool supportsIoNiceness(); 0136 0137 /** 0138 * Return the internal pointer of all the processes. The order of the processes 0139 * is guaranteed to never change. Call updateAllProcesses() first to actually 0140 * update the information. 0141 */ 0142 const QList<Process *> &getAllProcesses() const; 0143 0144 /** 0145 * Return the number of processes. Call updateAllProcesses() to actually 0146 * update the information. 0147 * 0148 * This is equivalent to getAllProcesses().count() 0149 */ 0150 int processCount() const; 0151 0152 /** 0153 * Return the total amount of physical memory in KB. This is fast (just a system call) 0154 * Returns 0 on error 0155 */ 0156 long long totalPhysicalMemory(); 0157 0158 /** 0159 * Return the number of processor cores enabled. 0160 * (A system can disable processors. Disabled processors are not counted here). 0161 * This is fast (just a system call) */ 0162 long numberProcessorCores(); 0163 0164 /** Update/add process for given pid immediately */ 0165 bool updateOrAddProcess(long pid); 0166 0167 /** Whether we can get historic process and system data */ 0168 bool isHistoryAvailable() const; 0169 0170 /** Stop using historical data and use the most recent up-to-date data */ 0171 void useCurrentData(); 0172 0173 /** Return a list of end times and intervals for all the available history */ 0174 QList<QPair<QDateTime, uint>> historiesAvailable() const; 0175 0176 /** Use historical process data closest to the given date-time. 0177 * Returns false if it is outside the range available or there is a problem 0178 * getting the data. */ 0179 bool setViewingTime(const QDateTime &when); 0180 QDateTime viewingTime() const; 0181 bool loadHistoryFile(const QString &filename); 0182 QString historyFileName() const; 0183 0184 public Q_SLOTS: 0185 /** The abstract processes has updated its list of processes */ 0186 void processesUpdated(); 0187 void processUpdated(long pid, const Process::Updates &changes); 0188 0189 Q_SIGNALS: 0190 /** The data for a process has changed. 0191 * if @p onlyTotalCpu is set, only the total cpu usage has been updated. 0192 * process->changes contains a bit field indicating what has changed since the last time this was emitted 0193 * for this process 0194 */ 0195 void processChanged(KSysGuard::Process *process, bool onlyTotalCpu); 0196 0197 /** 0198 * This indicates we are about to add a process in the model. 0199 * The process already has the pid, ppid and tree_parent set up. 0200 */ 0201 void beginAddProcess(KSysGuard::Process *process); 0202 0203 /** 0204 * We have finished inserting a process 0205 */ 0206 void endAddProcess(); 0207 /** 0208 * This indicates we are about to remove a process in the model. Emit the appropriate signals 0209 */ 0210 0211 void beginRemoveProcess(KSysGuard::Process *process); 0212 0213 /** 0214 * We have finished removing a process 0215 */ 0216 void endRemoveProcess(); 0217 0218 /** 0219 * This indicates we are about move a process from one parent to another. 0220 */ 0221 void beginMoveProcess(KSysGuard::Process *process, KSysGuard::Process *new_parent); 0222 0223 /** 0224 * We have finished moving the process 0225 */ 0226 void endMoveProcess(); 0227 0228 void updated(); 0229 0230 protected: 0231 class Private; 0232 Private *d; 0233 0234 private: 0235 inline void deleteProcess(long pid); 0236 bool updateProcess(Process *process, long ppid); 0237 bool updateProcessInfo(Process *ps); 0238 bool addProcess(long pid, long ppid); 0239 0240 Q_SIGNALS: 0241 /** For a remote machine, we rely on being able to communicate with ksysguardd. 0242 * This must be dealt with by the program including this widget. It must listen to our 0243 * 'runCommand' signal, and run the given command, with the given id. */ 0244 void runCommand(const QString &command, int id); 0245 0246 public: 0247 /** For a remote machine, we rely on being able to communicate with ksysguardd. 0248 * The programming using this must call this slot when an answer is received from ksysguardd, 0249 * in response to a runCommand request. The id identifies the answer */ 0250 void answerReceived(int id, const QList<QByteArray> &answer); 0251 }; 0252 Q_DECLARE_OPERATORS_FOR_FLAGS(Processes::UpdateFlags) 0253 } 0254 0255 #endif