mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-12 12:14:36 +03:00
Added preliminary attempt at jails support on FreeBSD - JID and JAIL (name) columns, somewhat more correct kernel "thread" detection.
Seems FreeBSD kernel can spawn both kernel processes (what is what htop currently sees) and kernel threads. For now let's consider kernel processes kernel "threads".
This commit is contained in:
@ -20,6 +20,12 @@ in the source distribution for its full text.
|
||||
/*{
|
||||
|
||||
#include <kvm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#define JAIL_ERRMSGLEN 1024
|
||||
char jail_errmsg[JAIL_ERRMSGLEN];
|
||||
|
||||
typedef struct CPUData_ {
|
||||
unsigned long long int totalTime;
|
||||
@ -58,13 +64,13 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui
|
||||
fpl->cpus[i].totalTime = 1;
|
||||
fpl->cpus[i].totalPeriod = 1;
|
||||
}
|
||||
|
||||
|
||||
size_t len;
|
||||
len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len);
|
||||
len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len);
|
||||
len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len);
|
||||
pageSizeKb = PAGE_SIZE_KB;
|
||||
|
||||
pageSizeKb = PAGE_SIZE_KB;
|
||||
|
||||
fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL);
|
||||
assert(fpl->kd);
|
||||
|
||||
@ -74,14 +80,14 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui
|
||||
void ProcessList_delete(ProcessList* this) {
|
||||
const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
|
||||
if (fpl->kd) kvm_close(fpl->kd);
|
||||
|
||||
|
||||
ProcessList_done(this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||
const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl;
|
||||
|
||||
|
||||
size_t len = sizeof(pl->totalMem);
|
||||
sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0);
|
||||
pl->totalMem /= 1024;
|
||||
@ -90,7 +96,7 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||
pl->freeMem = pl->totalMem - pl->usedMem;
|
||||
sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0);
|
||||
pl->cachedMem *= pageSizeKb;
|
||||
|
||||
|
||||
struct kvm_swap swap[16];
|
||||
int nswap = kvm_getswapinfo(fpl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0);
|
||||
pl->totalSwap = 0;
|
||||
@ -101,7 +107,7 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||
}
|
||||
pl->totalSwap *= pageSizeKb;
|
||||
pl->usedSwap *= pageSizeKb;
|
||||
|
||||
|
||||
pl->sharedMem = 0; // currently unused
|
||||
pl->buffersMem = 0; // not exposed to userspace
|
||||
}
|
||||
@ -131,27 +137,75 @@ char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in
|
||||
return comm;
|
||||
}
|
||||
|
||||
char* FreeBSDProcessList_readJailName(struct kinfo_proc* kproc) {
|
||||
int jid;
|
||||
struct iovec jiov[6];
|
||||
char* jname;
|
||||
char jnamebuf[MAXHOSTNAMELEN];
|
||||
|
||||
if (kproc->ki_jid != 0 ){
|
||||
memset(jnamebuf, 0, sizeof(jnamebuf));
|
||||
*(const void **)&jiov[0].iov_base = "jid";
|
||||
jiov[0].iov_len = sizeof("jid");
|
||||
jiov[1].iov_base = &kproc->ki_jid;
|
||||
jiov[1].iov_len = sizeof(kproc->ki_jid);
|
||||
*(const void **)&jiov[2].iov_base = "name";
|
||||
jiov[2].iov_len = sizeof("name");
|
||||
jiov[3].iov_base = jnamebuf;
|
||||
jiov[3].iov_len = sizeof(jnamebuf);
|
||||
*(const void **)&jiov[4].iov_base = "errmsg";
|
||||
jiov[4].iov_len = sizeof("errmsg");
|
||||
jiov[5].iov_base = jail_errmsg;
|
||||
jiov[5].iov_len = JAIL_ERRMSGLEN;
|
||||
jail_errmsg[0] = 0;
|
||||
jid = jail_get(jiov, 6, 0);
|
||||
if (jid < 0) {
|
||||
if (!jail_errmsg[0])
|
||||
snprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s", strerror(errno));
|
||||
return NULL;
|
||||
} else if (jid == kproc->ki_jid) {
|
||||
jname = strdup(jnamebuf);
|
||||
if (jname == NULL)
|
||||
strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
|
||||
return jname;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
jnamebuf[0]='-';
|
||||
jnamebuf[1]='\0';
|
||||
jname = strdup(jnamebuf);
|
||||
}
|
||||
return jname;
|
||||
}
|
||||
|
||||
void ProcessList_goThroughEntries(ProcessList* this) {
|
||||
FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
|
||||
Settings* settings = this->settings;
|
||||
bool hideKernelThreads = settings->hideKernelThreads;
|
||||
bool hideUserlandThreads = settings->hideUserlandThreads;
|
||||
|
||||
|
||||
FreeBSDProcessList_scanMemoryInfo(this);
|
||||
|
||||
|
||||
int count = 0;
|
||||
struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_ALL, 0, &count);
|
||||
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
struct kinfo_proc* kproc = &kprocs[i];
|
||||
|
||||
|
||||
bool preExisting = false;
|
||||
Process* proc = ProcessList_getProcess(this, kproc->ki_pid, &preExisting, (Process_New) FreeBSDProcess_new);
|
||||
FreeBSDProcess* fp = (FreeBSDProcess*) proc;
|
||||
|
||||
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
||||
|
||||
proc->show = ! ((hideKernelThreads && Process_isKernelThread(fp)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
||||
|
||||
if (!preExisting) {
|
||||
fp->jid = kproc->ki_jid;
|
||||
proc->pid = kproc->ki_pid;
|
||||
if ( ! ((kproc->ki_pid == 0) || (kproc->ki_pid == 1) ) && kproc->ki_flag & P_SYSTEM)
|
||||
fp->kernel = 1;
|
||||
else
|
||||
fp->kernel = 0;
|
||||
proc->ppid = kproc->ki_ppid;
|
||||
proc->tpgid = kproc->ki_tpgid;
|
||||
proc->tgid = kproc->ki_pid;
|
||||
@ -163,6 +217,7 @@ void ProcessList_goThroughEntries(ProcessList* this) {
|
||||
proc->user = UsersTable_getRef(this->usersTable, proc->st_uid);
|
||||
ProcessList_add((ProcessList*)this, proc);
|
||||
proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset);
|
||||
fp->jname = FreeBSDProcessList_readJailName(kproc);
|
||||
} else {
|
||||
if (settings->updateProcessNames) {
|
||||
free(proc->comm);
|
||||
@ -174,8 +229,12 @@ void ProcessList_goThroughEntries(ProcessList* this) {
|
||||
proc->m_resident = kproc->ki_rssize; // * pageSizeKb;
|
||||
proc->nlwp = kproc->ki_numthreads;
|
||||
proc->time = (kproc->ki_runtime + 5000) / 10000;
|
||||
|
||||
proc->priority = kproc->ki_pri.pri_level - PZERO;
|
||||
if (kproc->ki_pri.pri_class == PRI_TIMESHARE) {
|
||||
|
||||
if (strcmp("intr", kproc->ki_comm) == 0 && kproc->ki_flag & P_SYSTEM) {
|
||||
proc->nice = 0; //@etosan: freebsd intr kernel process (not thread) has weird nice value
|
||||
} else if (kproc->ki_pri.pri_class == PRI_TIMESHARE) {
|
||||
proc->nice = kproc->ki_nice - NZERO;
|
||||
} else if (PRI_IS_REALTIME(kproc->ki_pri.pri_class)) {
|
||||
proc->nice = PRIO_MIN - 1 - (PRI_MAX_REALTIME - kproc->ki_pri.pri_level);
|
||||
@ -183,6 +242,7 @@ void ProcessList_goThroughEntries(ProcessList* this) {
|
||||
proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE;
|
||||
}
|
||||
|
||||
|
||||
switch (kproc->ki_stat) {
|
||||
case SIDL: proc->state = 'I'; break;
|
||||
case SRUN: proc->state = 'R'; break;
|
||||
@ -194,10 +254,10 @@ void ProcessList_goThroughEntries(ProcessList* this) {
|
||||
default: proc->state = '?';
|
||||
}
|
||||
|
||||
if (Process_isKernelThread(proc)) {
|
||||
if (Process_isKernelThread(fp)) {
|
||||
this->kernelThreads++;
|
||||
}
|
||||
|
||||
|
||||
this->totalTasks++;
|
||||
if (proc->state == 'R')
|
||||
this->runningTasks++;
|
||||
|
Reference in New Issue
Block a user