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