File indexing completed on 2024-04-28 16:49:55

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