Logo Search packages:      
Sourcecode: qps version File versions  Download package

proc.h

// proc.h                     emacs, this is written in -*-c++-*-
//
// This program is free software. See the file COPYING for details.
// Author: Mattias Engdegård, 1997-1999

#ifndef PROC_H
#define PROC_H


#include "config.h"

#include <unistd.h>
#include <sys/time.h>

#ifdef SOLARIS
#include <inttypes.h>
#include <procfs.h>
#include <kstat.h>
#endif

#include <qstring.h>
#include <qwindowdefs.h>
#include <qintdict.h>
#include "svec.h"

#if QT_VERSION >= 200 && !defined(QTNAME)
#define QTNAME(x) Qt::x
#else
#define QTNAME(x) x
#endif

enum fields {
    F_PID, F_PPID, F_PGID, F_SID, F_TTY,
#ifdef LINUX
    F_TPGID,
#endif
#ifdef MOSIX
    F_MIGR,
    F_LOCKED,
    F_NMIGS,
    F_NOMOVE,
    F_RPID,
#endif
    F_USER, F_GROUP,
    F_UID, F_EUID,
#ifdef LINUX
    F_SUID, F_FSUID,
#endif
    F_GID, F_EGID,
#ifdef LINUX
    F_SGID, F_FSGID,
#endif
    F_PRI, F_NICE,
    F_PLCY, F_RPRI,
#ifdef SOLARIS
    F_NLWP,
#endif
    F_MAJFLT, F_MINFLT,
#ifdef LINUX
    F_TRS, F_DRS,
#endif
    F_SIZE, F_SWAP, F_RSS,
#ifdef LINUX
    F_SHARE, F_DT,
#endif
    F_STAT,
    F_FLAGS,
    F_WCHAN,
    F_WCPU, F_CPU, F_MEM,
    F_START, F_TIME,
    F_CPUNUM,
    F_COMM,
    F_CWD, F_ROOT,
    F_CMDLINE,
    F_END = -1 };

class Details;

#ifdef LINUX

class Sockinfo
{
public:
    enum proto_t { TCP, UDP };
    proto_t proto;
    unsigned char st;
    unsigned char tr;
    unsigned local_addr;
    unsigned rem_addr;
    unsigned short local_port;
    unsigned short rem_port;
    unsigned tx_queue;
    unsigned rx_queue;
    unsigned tm_when;
    unsigned rexmits;
    int uid;
    int timeout;
    int inode;
};

#endif // LINUX

class Mapsinfo
{     
public:
    unsigned long from, to;
    unsigned long offset;
    unsigned long inode;
    QString filename;         // null if name unknown
    char perm[4];       // "rwx[ps]"; last is private/shared flag
    unsigned char minor, major;
};

#define OPEN_READ 1
#define OPEN_WRITE 2

class Fileinfo
{
public:
    Fileinfo(int descr, QString name, int open_mode = 0)
      : fd(descr), filename(name), mode(open_mode) {};
    int fd;
    QString filename;         // "major:minor inode" in Linux 2.0,
                        // texual description in Solaris 2.6
    unsigned mode;            // bits from OPEN_* above (Linux only)
};

#ifdef LINUX

class SockInode
{
public:
    SockInode(int descr, unsigned long ino) : fd(descr), inode(ino) {};
    int fd;
    unsigned long inode;
};

class UnixSocket
{
public:
    unsigned long inode;
    QString name;
    unsigned flags;
    unsigned char type;       // probably SOCK_STREAM or SOCK_DGRAM
    unsigned char state;      // SS_FREE, SS_UNCONNECTED, SS_CONNECTING,
                        // SS_CONNECTED, SS_DISCONNECTING
};

#endif // LINUX

class NameValue
{
public:
    NameValue(const char *n, const char *val) : name(n), value(val) {};
    const char *name;
    const char *value;
};

class Procinfo
{
public:
    Procinfo(int pid);
    ~Procinfo();
    Procinfo *ref() { refcnt++; return this; };
    void deref() { if(!--refcnt) delete this; };

    int readproc(int pid);
    static void init_static();
    static void read_common();
    static void read_loadavg();
    static int read_file(char *name, void *buf, int max);
    void read_fd(int fdnum, char *path);
    bool read_fds();
    bool read_maps();
    bool read_environ();
#ifdef MOSIX
    static void check_for_mosix();
    static Svec<int> mosix_nodes();
#endif
#ifdef LINUX
    static bool read_socket_list(Sockinfo::proto_t proto, char *pseudofile);
    static void read_sockets();
    static bool read_usocket_list();
    static void read_usockets();
    static void invalidate_sockets();
#endif
    int get_policy();
    int get_rtprio();

    int pid;

    int uid, euid;
    int gid, egid;
#ifdef LINUX
    int suid, fsuid;
    int sgid, fsgid;
#endif

    QString cmdline;

    QString comm;
    char state;
    int ppid;
    int pgrp;
    int session;
    int tty;
#ifdef LINUX
    int tpgid;
#endif
    unsigned long flags;
    unsigned long minflt;
    unsigned long majflt;
#ifdef LINUX
    unsigned long cminflt;
    unsigned long cmajflt;
#endif
    long utime;
    long cutime;
    int priority;
    int nice;
    unsigned long starttime;  // in jiffies since boot
    unsigned long wchan;

    unsigned long size;       // total memory (K)
    unsigned long resident;   // pages in resident set (non-swapped) (K)
#ifdef LINUX
    unsigned long share;      // shared memory pages (mmaped) (K)
    unsigned long trs;        // text resident set size (K)
    unsigned long lrs;        // shared-lib resident set size (K)
    unsigned long drs;        // data resident set size (K)
    unsigned long dt;         // dirty pages (number of pages, not K)
#endif

#ifdef SOLARIS
    int nthreads;       // number of LWPs
#endif

    struct timeval tv;        // time when the snapshot was taken

    // Posix.1b scheduling
    int policy;         // -1 = uninitialized
#ifdef SOLARIS
    char policy_name[2];      // two first letters of scheduling class
#endif
    int rtprio;         // 0-99, higher can pre-empt lower (-1 = uninitialized)

#ifdef LINUX
    // from proc/XX/cpu (in 2.2 SMP kernels)
    unsigned long *per_cpu_times; // vector of num_cpus times
#endif
    // Linux: the cpu used most of the time of the process
    // Solaris: the cpu on which the process last ran
    int which_cpu;

    // computed %cpu and %mem since last update
    float wcpu;
    float pcpu;
    float pmem;

    static float loadavg[3];  // 1, 5 and 15 minutes load avgs

    // these are in kB
    static int mem_total, mem_free;
#ifdef LINUX
    static int mem_shared, mem_buffers, mem_cached;
#endif
    static int swap_total, swap_free;

    // Solaris <sys/sysinfo.h> #defines CPU_xxx so we must avoid them
    enum { CPUTIME_USER,
#ifdef LINUX
         CPUTIME_NICE,
#endif
         CPUTIME_SYSTEM,
#ifdef SOLARIS
         CPUTIME_WAIT,
#endif
         CPUTIME_IDLE,
         CPUTIMES };

    // the following are pointers to matrices indexed by kind (above) and cpu
    static unsigned *cpu_times_vec;
    static unsigned *old_cpu_times_vec;

    static unsigned num_cpus;       // current number of CPUs
    static unsigned old_num_cpus;   // previous number of CPUs

    // accessors for (old_)cpu_times_vec
    static unsigned &cpu_times(int cpu, int kind)
    { return cpu_times_vec[cpu * CPUTIMES + kind]; }
    static unsigned &old_cpu_times(int cpu, int kind)
    { return old_cpu_times_vec[cpu * CPUTIMES + kind]; }

    static long boot_time;    // seconds since epoch

#ifdef LINUX
    // from /proc/net/{tcp,udp,unix}
    static QIntDict<Sockinfo> socks;      // tcp/udp sockets
    static bool socks_current;            // true if the socks list is current
    static QIntDict<UnixSocket> usocks;   // unix domain sockets
    static bool usocks_current;           // true if the usocks list is current
#endif

    Svec<Fileinfo*> *fd_files;      // file names or NULL if not read
    Svec<Mapsinfo*> *maps;    // maps or NULL if not read

    QString cwd;        // null if not read
    QString root;       // null if not read

#ifdef LINUX
    Svec<SockInode> *sock_inodes; // socket inodes or NULL if not read
#endif

    Svec<NameValue> *environ; // environment or NULL if not read
    char *envblock;           // malloc()ed environment data block

#ifdef SOLARIS
    unsigned long env_ofs;

    static kstat_ctl_t *kc;         // NULL if kstat not opened
#endif

    Details *details;         // details window or NULL (backlink)

    bool selected:1;    // true if selected in current view
    bool generation:1;  // whether new or old generation (alternating)
    bool hidekids:1;    // true if children are hidden in tree view
    bool lastchild:1;   // true if last (visible) child in tree view

    Svec<Procinfo *> *children;     // children or NULL if none (or uninit'ed)
    short level;        // distance from process root

    static const int MAX_CMD_LEN = 4096;
    static int page_k_shift;  // log2(pagesize / 1024)

    char refcnt;

#ifdef MOSIX
    bool isremote;
    int from;
    int where;
    int remotepid;
    QString migr; // String explaining migration "node>" or ">node" 
    int nmigs;
    int locked;
    QString cantmove;

    static bool mosix_running;      // true if MOSIX is running
#endif
};

class Category
{
public:
    Category(const char *heading, const char *explain)
      : name(heading), help(explain) {};
    virtual ~Category();

    virtual int alignment() = 0;
    virtual QString string(Procinfo *p) = 0;
    virtual int width() = 0;
    virtual int compare(Procinfo *a, Procinfo *b);
    virtual int gap() { return 0; };

    const char *name;
    const char *help;
    int index;
};

class Cat_int : public Category
{
public:
    Cat_int(const char *heading, const char *explain,
          int w, int Procinfo::*member);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return field_width; };
    virtual int compare(Procinfo *a, Procinfo *b);

protected:
    int Procinfo::*int_member;
    int field_width;
};

class Cat_uintl : public Category
{
public:
    Cat_uintl(const char *heading, const char *explain, int w,
            unsigned long Procinfo::*member);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return field_width; };
    virtual int compare(Procinfo *a, Procinfo *b);

protected:
    unsigned long Procinfo::*uintl_member;
    int field_width;
};

class Cat_hex : public Cat_uintl
{
public:
    Cat_hex(const char *heading, const char *explain, int w,
          unsigned long Procinfo::*member);
    virtual QString string(Procinfo *p);
};

class Cat_swap : public Category
{
public:
    Cat_swap(const char *heading, const char *explain);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return 8; };
    virtual int compare(Procinfo *a, Procinfo *b);
};

class Cat_string : public Category
{
public:
    Cat_string(const char *heading, const char *explain,
             QString Procinfo::*member = 0);
    virtual int alignment() { return QTNAME(AlignLeft); };
    virtual QString string(Procinfo *p);
    virtual int width() { return -1; };
    virtual int gap() { return 8; };

protected:
    QString Procinfo::*str_member;
};

class Cat_user : public Cat_string
{
public:
    Cat_user(const char *heading, const char *explain);
    virtual QString string(Procinfo *p);
};

class Cat_group : public Cat_string
{
public:
    Cat_group(const char *heading, const char *explain);
    virtual QString string(Procinfo *p);
};

class Cat_wchan : public Cat_string
{
public:
    Cat_wchan(const char *heading, const char *explain);
    virtual QString string(Procinfo *p);
};

class Cat_dir : public Cat_string
{
public:
    Cat_dir(const char *heading, const char *explain, const char *dirname,
          QString Procinfo::*member);
    virtual QString string(Procinfo *p);

protected:
    const char *dir;
    QString Procinfo::*cache;
};

class Cat_cmdline : public Cat_string
{
public:
    Cat_cmdline(const char *heading, const char *explain);
    virtual QString string(Procinfo *p);
};

class Cat_state : public Category
{
public:
    Cat_state(const char *heading, const char *explain);
    virtual int alignment() { return QTNAME(AlignLeft); };
    virtual QString string(Procinfo *p);
    virtual int width() { return 6; };
    virtual int gap() { return 8; };
};

class Cat_policy : public Category
{
public:
    Cat_policy(const char *heading, const char *explain);
    virtual int alignment() { return QTNAME(AlignLeft); };
    virtual QString string(Procinfo *p);
    virtual int width() { return 3; };
    virtual int gap() { return 8; };
    virtual int compare(Procinfo *a, Procinfo *b);
};

class Cat_rtprio : public Category
{
public:
    Cat_rtprio(const char *heading, const char *explain);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return 5; };
    virtual int compare(Procinfo *a, Procinfo *b);
};

class Cat_time : public Category
{
public:
    Cat_time(const char *heading, const char *explain);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return 7; };
    virtual int compare(Procinfo *a, Procinfo *b);
};

class Cat_start : public Category
{
public:
    Cat_start(const char *heading, const char *explain);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return 8; };
    virtual int compare(Procinfo *a, Procinfo *b);
};

class Cat_percent : public Category
{
public:
    Cat_percent(const char *heading, const char *explain,
            int w, float Procinfo::*member);
    virtual int alignment() { return QTNAME(AlignRight); };
    virtual QString string(Procinfo *p);
    virtual int width() { return field_width; };
    virtual int compare(Procinfo *a, Procinfo *b);

protected:
    float Procinfo::*float_member;
    int field_width;
};

class Cat_tty : public Cat_string
{
public:
    Cat_tty(const char *heading, const char *explain);
    virtual QString string(Procinfo *p);
};

class Proc
{
public:
    Proc();
    void refresh();
    void newproc(Procinfo *p);

    QIntDict<Procinfo> procs; // processes indexed by pid
    Svec<Category *> allcats;
};

class Procview
{
public:
    Procview(Proc *p);

    static int compare(Procinfo *const *a, Procinfo *const *b);
    static int compare_backwards(Procinfo *const *a, Procinfo *const *b);
    void refresh();
    void rebuild();
    bool accept_proc(Procinfo *p);
    void linearize_tree(Svec<Procinfo *> *ps, int level, int prow);
    void build_tree();

    void set_fields();
    void set_fields_list(int fields[]);
    void add_cat(Category *c);
    void remove_cat(int index);
    int findCol(int field);
    
    Svec<Procinfo *> procs;
    Svec<Procinfo *> old_procs;

    // root_procs contains processes without parent; normally only init, but
    // we cannot rely on this (Solaris has several parentless processes).
    // Also, if the view is restricted, all processes whose parent isn't in
    // the table.
    Svec<Procinfo *> root_procs;
    Svec<int> parent_rows;

    Svec<Category *> cats;
    Category *sortcat;
    bool reversed;            // true if sorted backwards
    bool treeview;            // true if viewed in tree form

    enum procstates {ALL, OWNED, NROOT, RUNNING} viewproc;
    enum fieldstates {USER = RUNNING + 1, JOBS, MEM, CUSTOM} viewfields;

    // lists of fields to be used for different views, terminated by -1:
    static int user_fields[];
    static int jobs_fields[];
    static int mem_fields[];
#ifdef MOSIX
    static int user_fields_mosix[];
    static int jobs_fields_mosix[];
    static int mem_fields_mosix[];
#endif
    static float avg_factor;        // exponential factor for averaging

    static const int cpu_avg_time = 30 * 1000;  // averaging time for WCPU (ms)

private:
    static Category *static_sortcat;      // kludge: to be used by compare

    Proc *proc;
};

#endif      // PROC_H

Generated by  Doxygen 1.6.0   Back to index