1 /* This file is part of the KDE project
2 Copyright (C) 2007 Manolo Valdes <nolis71cu@gmail.com>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "processes_local_p.h"
27 #include <sys/param.h>
28 #include <sys/sysctl.h>
29 #include <sys/types.h>
31 #include <sys/resource.h>
32 #if defined(__DragonFly__)
33 #include <sys/resourcevar.h>
46 class ProcessesLocal::Private
51 inline bool readProc(long pid
, struct kinfo_proc
*p
);
52 inline void readProcStatus(struct kinfo_proc
*p
, Process
*process
);
53 inline void readProcStat(struct kinfo_proc
*p
, Process
*process
);
54 inline void readProcStatm(struct kinfo_proc
*p
, Process
*process
);
55 inline bool readProcCmdline(long pid
, Process
*process
);
58 bool ProcessesLocal::Private::readProc(long pid
, struct kinfo_proc
*p
)
65 mib
[2] = KERN_PROC_PID
;
68 len
= sizeof (struct kinfo_proc
);
69 if (sysctl(mib
, 4, p
, &len
, NULL
, 0) == -1 || !len
)
74 void ProcessesLocal::Private::readProcStatus(struct kinfo_proc
*p
, Process
*process
)
78 process
->setTracerpid(0);
81 #if defined(__FreeBSD__)
82 process
->setEuid(p
->ki_uid
);
83 process
->setUid(p
->ki_ruid
);
84 process
->setEgid(p
->ki_svgid
);
85 process
->setGid(p
->ki_rgid
);
86 process
->setName(QString(p
->ki_comm
? p
->ki_comm
: "????"));
87 #elif defined(__DragonFly__) && __DragonFly_version >= 190000
88 process
->setUid(p
->kp_uid
);
89 process
->setGid(p
->kp_pgid
);
90 process
->setName(QString(p
->kp_comm
? p
->kp_comm
: "????"));
92 process
->setUid(p
->kp_eproc
.e_ucred
.cr_uid
);
93 process
->setGid(p
->kp_eproc
.e_pgid
);
97 void ProcessesLocal::Private::readProcStat(struct kinfo_proc
*p
, Process
*ps
)
101 #if defined(__FreeBSD__)
102 ps
->setUserTime(p
->ki_rusage
.ru_utime
.tv_sec
* 100 + p
->ki_rusage
.ru_utime
.tv_usec
/ 10000);
103 ps
->setSysTime(p
->ki_rusage
.ru_stime
.tv_sec
* 100 + p
->ki_rusage
.ru_stime
.tv_usec
/ 10000);
104 ps
->setNiceLevel(p
->ki_nice
);
105 ps
->setVmSize(p
->ki_size
/ 1024);
106 ps
->setVmRSS(p
->ki_rssize
* getpagesize() / 1024);
108 #elif defined(__DragonFly__)
109 #if __DragonFly_version >= 190000
110 if (!getrusage(p
->kp_pid
, &pru
)) {
111 errx(1, "failed to get rusage info");
113 ps
->setUserTime(pru
.ru_utime
.tv_usec
/ 1000); /*p_runtime / 1000*/
114 ps
->setNiceLevel(p
->kp_nice
);
115 ps
->setVmSize(p
->kp_vm_map_size
);
116 ps
->setVmRSS(p
->kp_vm_rssize
* getpagesize());
119 ps
->setUserTime(p
->kp_proc
.p_rtime
.tv_sec
*100+p
->kp_proc
.p_rtime
.tv_usec
/100);
120 ps
->setNiceLevel(p
->kp_proc
.p_nice
);
121 ps
->setVmSize(p
->kp_eproc
.e_vm
.vm_map
.size
);
122 ps
->setVmRSS(p
->kp_eproc
.e_vm
.vm_rssize
* getpagesize());
123 status
= p
->kp_proc
.p_stat
;
128 // "idle","run","sleep","stop","zombie"
131 ps
->setStatus(Process::Running
);
136 ps
->setStatus(Process::Sleeping
);
139 ps
->setStatus(Process::Stopped
);
142 ps
->setStatus(Process::Zombie
);
145 ps
->setStatus(Process::OtherStatus
);
150 void ProcessesLocal::Private::readProcStatm(struct kinfo_proc
*p
, Process
*process
)
152 process
->setVmURSS(-1);
155 bool ProcessesLocal::Private::readProcCmdline(long pid
, Process
*process
)
164 mib
[2] = KERN_PROC_ARGS
;
167 if (sysctl(mib
, 4, buf
, &buflen
, NULL
, 0) == -1 || !buflen
)
169 QString command
= QString(buf
);
171 //cmdline seperates parameters with the NULL character
172 command
= command
.replace('\0', ' ');
173 process
->setCommand(command
.trimmed());
178 ProcessesLocal::ProcessesLocal() : d(new Private())
183 long ProcessesLocal::getParentPid(long pid
) {
186 if(d
->readProc(pid
, &p
))
188 #if defined(__FreeBSD__)
190 #elif defined(__DragonFly__) && __DragonFly_version >= 190000
193 ppid
= p
.kp_eproc
.e_ppid
;
199 bool ProcessesLocal::updateProcessInfo( long pid
, Process
*process
)
202 if(!d
->readProc(pid
, &p
)) return false;
203 d
->readProcStat(&p
, process
);
204 d
->readProcStatus(&p
, process
);
205 d
->readProcStatm(&p
, process
);
206 if(!d
->readProcCmdline(pid
, process
)) return false;
211 QSet
<long> ProcessesLocal::getAllPids( )
217 struct kinfo_proc
*p
;
221 mib
[2] = KERN_PROC_ALL
;
222 if (sysctl(mib
, 3, NULL
, &len
, NULL
, 0) == -1)
224 if ((p
= (kinfo_proc
*) malloc(len
)) == NULL
)
226 if (sysctl(mib
, 3, p
, &len
, NULL
, 0) == -1) {
231 for (num
= 0; num
< len
/ sizeof(struct kinfo_proc
); num
++)
233 #if defined(__FreeBSD__)
234 long pid
= p
[num
].ki_pid
;
235 long long ppid
= p
[num
].ki_ppid
;
236 #elif defined(__DragonFly__) && __DragonFly_version >= 190000
237 long pid
= p
[num
].kp_pid
;
238 long long ppid
= p
[num
].kp_ppid
;
240 long pid
= p
[num
].kp_proc
.p_pid
;
241 long long ppid
= p
[num
].kp_eproc
.e_ppid
;
243 //skip all process with parent id = 0 but init
244 if(ppid
== 0 && pid
!= 1)
252 bool ProcessesLocal::sendSignal(long pid
, int sig
) {
253 if ( kill( (pid_t
)pid
, sig
) ) {
260 bool ProcessesLocal::setNiceness(long pid
, int priority
) {
261 if ( setpriority( PRIO_PROCESS
, pid
, priority
) ) {
262 //set niceness failed
268 bool ProcessesLocal::setScheduler(long pid
, int priorityClass
, int priority
)
270 if(priorityClass
== KSysGuard::Process::Other
|| priorityClass
== KSysGuard::Process::Batch
)
272 if(pid
<= 0) return false; // check the parameters
273 struct sched_param params
;
274 params
.sched_priority
= priority
;
275 switch(priorityClass
) {
276 case (KSysGuard::Process::Other
):
277 return (sched_setscheduler( pid
, SCHED_OTHER
, ¶ms
) == 0);
278 case (KSysGuard::Process::RoundRobin
):
279 return (sched_setscheduler( pid
, SCHED_RR
, ¶ms
) == 0);
280 case (KSysGuard::Process::Fifo
):
281 return (sched_setscheduler( pid
, SCHED_FIFO
, ¶ms
) == 0);
283 case (KSysGuard::Process::Batch
):
284 return (sched_setscheduler( pid
, SCHED_BATCH
, ¶ms
) == 0);
291 bool ProcessesLocal::setIoNiceness(long pid
, int priorityClass
, int priority
) {
292 return false; //Not yet supported
295 bool ProcessesLocal::supportsIoNiceness() {
299 long long ProcessesLocal::totalPhysicalMemory() {
304 len
= sizeof (Total
);
305 if (sysctlbyname("hw.physmem", &Total
, &len
, NULL
, 0) == -1)
308 return Total
/= 1024;
311 ProcessesLocal::~ProcessesLocal()