summaryrefslogtreecommitdiffstats
path: root/freebsd
diff options
context:
space:
mode:
authorMartin "eto" Misuth <et.code@ethome.sk>2015-09-30 22:04:26 +0200
committerMartin "eto" Misuth <et.code@ethome.sk>2015-09-30 22:04:26 +0200
commit8c00fa45822041f67bb9bf89ed01c90365a04c1b (patch)
tree4da293e03777981142f50c2a16dd738976264153 /freebsd
parent2d1507ad5a670a612aa3eb53c0636cae5f0abbbf (diff)
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".
Diffstat (limited to 'freebsd')
-rw-r--r--freebsd/FreeBSDProcess.c40
-rw-r--r--freebsd/FreeBSDProcessList.c92
2 files changed, 111 insertions, 21 deletions
diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c
index 43fd88d5..ee542b4d 100644
--- a/freebsd/FreeBSDProcess.c
+++ b/freebsd/FreeBSDProcess.c
@@ -12,6 +12,7 @@ in the source distribution for its full text.
#include "CRT.h"
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
@@ -19,15 +20,22 @@ in the source distribution for its full text.
typedef enum FreeBSDProcessFields {
// Add platform-specific fields here, with ids >= 100
- LAST_PROCESSFIELD = 100,
+ JID = 100,
+ JAIL = 101,
+ LAST_PROCESSFIELD = 102,
} FreeBSDProcessField;
+
typedef struct FreeBSDProcess_ {
Process super;
+ int kernel;
+ int jid;
+ char* jname;
} FreeBSDProcess;
+
#ifndef Process_isKernelThread
-#define Process_isKernelThread(_process) (_process->pgrp == 0)
+#define Process_isKernelThread(_process) (_process->kernel == 1)
#endif
#ifndef Process_isUserlandThread
@@ -72,10 +80,13 @@ ProcessFieldData Process_fields[] = {
[TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, },
[NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, },
[TGID] = { .name = "TGID", .title = " TGID ", .description = "Thread group ID (i.e. process ID)", .flags = 0, },
+ [JID] = { .name = "JID", .title = " JID ", .description = "Jail prison ID", .flags = 0, },
+ [JAIL] = { .name = "JAIL", .title = "JAIL ", .description = "Jail prison name", .flags = 0, },
[LAST_PROCESSFIELD] = { .name = "*** report bug! ***", .title = NULL, .description = NULL, .flags = 0, },
};
ProcessPidColumn Process_pidColumns[] = {
+ { .id = JID, .label = "JID" },
{ .id = PID, .label = "PID" },
{ .id = PPID, .label = "PPID" },
{ .id = TPGID, .label = "TPGID" },
@@ -95,16 +106,26 @@ FreeBSDProcess* FreeBSDProcess_new(Settings* settings) {
void Process_delete(Object* cast) {
FreeBSDProcess* this = (FreeBSDProcess*) cast;
Process_done((Process*)cast);
+ free(this->jname);
free(this);
}
void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField field) {
- //FreeBSDProcess* fp = (FreeBSDProcess*) this;
+ FreeBSDProcess* fp = (FreeBSDProcess*) this;
char buffer[256]; buffer[255] = '\0';
int attr = CRT_colors[DEFAULT_COLOR];
- //int n = sizeof(buffer) - 1;
+ int n = sizeof(buffer) - 1;
switch (field) {
// add FreeBSD-specific fields here
+ case JID: snprintf(buffer, n, Process_pidFormat, fp->jid); break;
+ case JAIL:{
+ snprintf(buffer, n, "%-11s ", fp->jname); break;
+ if (buffer[11] != '\0') {
+ buffer[11] = ' ';
+ buffer[12] = '\0';
+ }
+ break;
+ }
default:
Process_writeField(this, str, field);
return;
@@ -124,11 +145,20 @@ long FreeBSDProcess_compare(const void* v1, const void* v2) {
}
switch (settings->sortKey) {
// add FreeBSD-specific fields here
+ case JID:
+ return (p1->jid - p2->jid);
+ case JAIL:
+ return strcmp(p1->jname ? p1->jname : "", p2->jname ? p2->jname : "");
default:
return Process_compare(v1, v2);
}
}
bool Process_isThread(Process* this) {
- return (Process_isKernelThread(this));
+ FreeBSDProcess* fp = (FreeBSDProcess*) this;
+
+ if (fp->kernel == 1 )
+ return 1;
+ else
+ return (Process_isUserlandThread(this));
}
diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c
index cc51a7cd..54ae7607 100644
--- a/freebsd/FreeBSDProcessList.c
+++ b/freebsd/FreeBSDProcessList.c
@@ -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++;

© 2014-2024 Faster IT GmbH | imprint | privacy policy