Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1310)

Unified Diff: third_party/psutil/psutil/_pslinux.py

Issue 6246123: Moving psutil to third_party. This is first step for Media Performance test project. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: modification based on code review's comments Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/psutil/psutil/_psbsd.py ('k') | third_party/psutil/psutil/_psmswindows.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/psutil/psutil/_pslinux.py
diff --git a/third_party/psutil/psutil/_pslinux.py b/third_party/psutil/psutil/_pslinux.py
new file mode 100755
index 0000000000000000000000000000000000000000..26a8abf55a6be0583b88f7a5dba320633c2168ea
--- /dev/null
+++ b/third_party/psutil/psutil/_pslinux.py
@@ -0,0 +1,471 @@
+#!/usr/bin/env python
+#
+# $Id: _pslinux.py 800 2010-11-12 21:51:25Z g.rodola $
+#
+
+__all__ = ["NUM_CPUS", "TOTAL_PHYMEM",
+ "PlatformProcess",
+ "avail_phymem", "used_phymem", "total_virtmem", "avail_virtmem",
+ "used_virtmem", "get_system_cpu_times", "pid_exists", "get_pid_list",
+ "phymem_buffers", "cached_phymem"
+ ]
+
+
+import os
+import errno
+import socket
+import struct
+import sys
+import base64
+
+try:
+ from collections import namedtuple
+except ImportError:
+ from psutil.compat import namedtuple # python < 2.6
+
+from psutil import _psposix
+from psutil.error import AccessDenied, NoSuchProcess
+
+
+def _get_uptime():
+ """Return system boot time (epoch in seconds)"""
+ f = open('/proc/stat', 'r')
+ for line in f:
+ if line.startswith('btime'):
+ f.close()
+ return float(line.strip().split()[1])
+
+def _get_num_cpus():
+ """Return the number of CPUs on the system"""
+ num = 0
+ f = open('/proc/cpuinfo', 'r')
+ for line in f:
+ if line.startswith('processor'):
+ num += 1
+ f.close()
+ return num
+
+def _get_total_phymem():
+ """Return the total amount of physical memory, in bytes"""
+ f = open('/proc/meminfo', 'r')
+ for line in f:
+ if line.startswith('MemTotal:'):
+ f.close()
+ return int(line.split()[1]) * 1024
+
+
+# Number of clock ticks per second
+_CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"])
+_UPTIME = _get_uptime()
+NUM_CPUS = _get_num_cpus()
+TOTAL_PHYMEM = _get_total_phymem()
+
+del _get_uptime, _get_num_cpus, _get_total_phymem
+
+# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
+_TCP_STATES_TABLE = {"01" : "ESTABLISHED",
+ "02" : "SYN_SENT",
+ "03" : "SYN_RECV",
+ "04" : "FIN_WAIT1",
+ "05" : "FIN_WAIT2",
+ "06" : "TIME_WAIT",
+ "07" : "CLOSE",
+ "08" : "CLOSE_WAIT",
+ "09" : "LAST_ACK",
+ "0A" : "LISTEN",
+ "0B" : "CLOSING"
+ }
+
+def avail_phymem():
+ """Return the amount of physical memory available, in bytes."""
+ f = open('/proc/meminfo', 'r')
+ free = None
+ _flag = False
+ for line in f:
+ if line.startswith('MemFree:'):
+ free = int(line.split()[1]) * 1024
+ break
+ f.close()
+ return free
+
+def used_phymem():
+ """"Return the amount of physical memory used, in bytes."""
+ return (TOTAL_PHYMEM - avail_phymem())
+
+def total_virtmem():
+ """"Return the total amount of virtual memory, in bytes."""
+ f = open('/proc/meminfo', 'r')
+ for line in f:
+ if line.startswith('SwapTotal:'):
+ f.close()
+ return int(line.split()[1]) * 1024
+
+def avail_virtmem():
+ """Return the amount of virtual memory currently in use on the
+ system, in bytes.
+ """
+ f = open('/proc/meminfo', 'r')
+ for line in f:
+ if line.startswith('SwapFree:'):
+ f.close()
+ return int(line.split()[1]) * 1024
+
+def used_virtmem():
+ """Return the amount of used memory currently in use on the system,
+ in bytes.
+ """
+ return total_virtmem() - avail_virtmem()
+
+def cached_phymem():
+ """Return the amount of cached memory on the system, in bytes.
+ This reflects the "cached" column of free command line utility.
+ """
+ f = open('/proc/meminfo', 'r')
+ for line in f:
+ if line.startswith('Cached:'):
+ f.close()
+ return int(line.split()[1]) * 1024
+
+def phymem_buffers():
+ """Return the amount of physical memory buffers used by the
+ kernel in bytes.
+ This reflects the "buffers" column of free command line utility.
+ """
+ f = open('/proc/meminfo', 'r')
+ for line in f:
+ if line.startswith('Buffers:'):
+ f.close()
+ return int(line.split()[1]) * 1024
+
+def get_system_cpu_times():
+ """Return a dict representing the following CPU times:
+ user, nice, system, idle, iowait, irq, softirq.
+ """
+ f = open('/proc/stat', 'r')
+ values = f.readline().split()
+ f.close()
+
+ values = values[1:8]
+ values = tuple([float(x) / _CLOCK_TICKS for x in values])
+
+ return dict(user=values[0], nice=values[1], system=values[2], idle=values[3],
+ iowait=values[4], irq=values[5], softirq=values[6])
+
+def get_pid_list():
+ """Returns a list of PIDs currently running on the system."""
+ pids = [int(x) for x in os.listdir('/proc') if x.isdigit()]
+ # special case for 0 (kernel process) PID
+ pids.insert(0, 0)
+ return pids
+
+def pid_exists(pid):
+ """Check For the existence of a unix pid."""
+ return _psposix.pid_exists(pid)
+
+
+# --- decorators
+
+def wrap_exceptions(callable):
+ """Call callable into a try/except clause and translate ENOENT,
+ EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
+ """
+ def wrapper(self, *args, **kwargs):
+ try:
+ return callable(self, *args, **kwargs)
+ except (OSError, IOError), err:
+ if err.errno == errno.ENOENT: # no such file or directory
+ raise NoSuchProcess(self.pid, self._process_name)
+ if err.errno in (errno.EPERM, errno.EACCES):
+ raise AccessDenied(self.pid, self._process_name)
+ raise
+ return wrapper
+
+
+class LinuxProcess(object):
+ """Linux process implementation."""
+
+ _meminfo_ntuple = namedtuple('meminfo', 'rss vms')
+ _cputimes_ntuple = namedtuple('cputimes', 'user system')
+ _openfile_ntuple = namedtuple('openfile', 'path fd')
+ _connection_ntuple = namedtuple('connection', 'fd family type local_address '
+ 'remote_address status')
+ __slots__ = ["pid", "_process_name"]
+
+ def __init__(self, pid):
+ self.pid = pid
+ self._process_name = None
+
+ @wrap_exceptions
+ def get_process_name(self):
+ if self.pid == 0:
+ return 'sched' # special case for kernel process
+ f = open("/proc/%s/stat" % self.pid)
+ try:
+ name = f.read().split(' ')[1].replace('(', '').replace(')', '')
+ finally:
+ f.close()
+ # XXX - gets changed later and probably needs refactoring
+ return name
+
+ def get_process_exe(self):
+ if self.pid in (0, 2):
+ return "" # special case for kernel processes
+ try:
+ exe = os.readlink("/proc/%s/exe" % self.pid)
+ except (OSError, IOError), err:
+ if err.errno == errno.ENOENT:
+ # no such file error; might be raised also if the
+ # path actually exists for system processes with
+ # low pids (about 0-20)
+ if os.path.lexists("/proc/%s/exe" % self.pid):
+ return ""
+ else:
+ # ok, it is a process which has gone away
+ raise NoSuchProcess(self.pid, self._process_name)
+ if err.errno in (errno.EPERM, errno.EACCES):
+ raise AccessDenied(self.pid, self._process_name)
+ raise
+
+ # It seems symlinks can point to a deleted/invalid location
+ # (this usually happens with "pulseaudio" process).
+ # However, if we had permissions to execute readlink() it's
+ # likely that we'll be able to figure out exe from argv[0]
+ # later on.
+ if exe.endswith(" (deleted)") and not os.path.isfile(exe):
+ return ""
+ return exe
+
+ @wrap_exceptions
+ def get_process_cmdline(self):
+ if self.pid == 0:
+ return [] # special case for kernel process
+ f = open("/proc/%s/cmdline" % self.pid)
+ try:
+ # return the args as a list
+ return [x for x in f.read().split('\x00') if x]
+ finally:
+ f.close()
+
+ @wrap_exceptions
+ def get_cpu_times(self):
+ # special case for 0 (kernel process) PID
+ if self.pid == 0:
+ return self._cputimes_ntuple(0.0, 0.0)
+ f = open("/proc/%s/stat" % self.pid)
+ st = f.read().strip()
+ f.close()
+ # ignore the first two values ("pid (exe)")
+ st = st[st.find(')') + 2:]
+ values = st.split(' ')
+ utime = float(values[11]) / _CLOCK_TICKS
+ stime = float(values[12]) / _CLOCK_TICKS
+ return self._cputimes_ntuple(utime, stime)
+
+ @wrap_exceptions
+ def get_process_create_time(self):
+ # special case for 0 (kernel processes) PID; return system uptime
+ if self.pid == 0:
+ return _UPTIME
+ f = open("/proc/%s/stat" % self.pid)
+ st = f.read().strip()
+ f.close()
+ # ignore the first two values ("pid (exe)")
+ st = st[st.find(')') + 2:]
+ values = st.split(' ')
+ # According to documentation, starttime is in field 21 and the
+ # unit is jiffies (clock ticks).
+ # We first divide it for clock ticks and then add uptime returning
+ # seconds since the epoch, in UTC.
+ starttime = (float(values[19]) / _CLOCK_TICKS) + _UPTIME
+ return starttime
+
+ @wrap_exceptions
+ def get_memory_info(self):
+ # special case for 0 (kernel processes) PID
+ if self.pid == 0:
+ return self._meminfo_ntuple(0, 0)
+ f = open("/proc/%s/status" % self.pid)
+ virtual_size = 0
+ resident_size = 0
+ _flag = False
+ for line in f:
+ if (not _flag) and line.startswith("VmSize:"):
+ virtual_size = int(line.split()[1]) * 1024
+ _flag = True
+ elif line.startswith("VmRSS"):
+ resident_size = int(line.split()[1]) * 1024
+ break
+ f.close()
+ return self._meminfo_ntuple(resident_size, virtual_size)
+
+ @wrap_exceptions
+ def get_process_cwd(self):
+ if self.pid == 0:
+ return ''
+ return os.readlink("/proc/%s/cwd" % self.pid)
+
+ @wrap_exceptions
+ def get_process_num_threads(self):
+ if self.pid == 0:
+ return 0
+ f = open("/proc/%s/status" % self.pid)
+ for line in f:
+ if line.startswith("Threads:"):
+ f.close()
+ return int(line.split()[1])
+
+ @wrap_exceptions
+ def get_open_files(self):
+ retlist = []
+ files = os.listdir("/proc/%s/fd" % self.pid)
+ for fd in files:
+ file = "/proc/%s/fd/%s" % (self.pid, fd)
+ if os.path.islink(file):
+ file = os.readlink(file)
+ if file.startswith("socket:["):
+ continue
+ if file.startswith("pipe:["):
+ continue
+ if file == "[]":
+ continue
+ if os.path.isfile(file) and not file in retlist:
+ ntuple = self._openfile_ntuple(file, int(fd))
+ retlist.append(ntuple)
+ return retlist
+
+# --- lsof implementation
+#
+# def get_open_files(self):
+# lsof = _psposix.LsofParser(self.pid, self._process_name)
+# return lsof.get_process_open_files()
+
+ @wrap_exceptions
+ def get_connections(self):
+ if self.pid == 0:
+ return []
+ inodes = {}
+ # os.listdir() is gonna raise a lot of access denied
+ # exceptions in case of unprivileged user; that's fine:
+ # lsof does the same so it's unlikely that we can to better.
+ for fd in os.listdir("/proc/%s/fd" % self.pid):
+ try:
+ inode = os.readlink("/proc/%s/fd/%s" % (self.pid, fd))
+ except OSError:
+ continue
+ if inode.startswith('socket:['):
+ # the process is using a socket
+ inode = inode[8:][:-1]
+ inodes[inode] = fd
+
+ if not inodes:
+ # no connections for this process
+ return []
+
+ def process(file, family, _type):
+ retlist = []
+ f = open(file)
+ f.readline() # skip the first line
+ for line in f:
+ _, laddr, raddr, status, _, _, _, _, _, inode = line.split()[:10]
+ if inode in inodes:
+ laddr = self._decode_address(laddr, family)
+ raddr = self._decode_address(raddr, family)
+ if _type == socket.SOCK_STREAM:
+ status = _TCP_STATES_TABLE[status]
+ else:
+ status = ""
+ fd = int(inodes[inode])
+ conn = self._connection_ntuple(fd, family, _type, laddr,
+ raddr, status)
+ retlist.append(conn)
+ f.close()
+ return retlist
+
+ tcp4 = process("/proc/net/tcp", socket.AF_INET, socket.SOCK_STREAM)
+ tcp6 = process("/proc/net/tcp6", socket.AF_INET6, socket.SOCK_STREAM)
+ udp4 = process("/proc/net/udp", socket.AF_INET, socket.SOCK_DGRAM)
+ udp6 = process("/proc/net/udp6", socket.AF_INET6, socket.SOCK_DGRAM)
+ return tcp4 + tcp6 + udp4 + udp6
+
+# --- lsof implementation
+#
+# def get_connections(self):
+# lsof = _psposix.LsofParser(self.pid, self._process_name)
+# return lsof.get_process_connections()
+
+ @wrap_exceptions
+ def get_process_ppid(self):
+ if self.pid == 0:
+ return 0
+ f = open("/proc/%s/status" % self.pid)
+ for line in f:
+ if line.startswith("PPid:"):
+ # PPid: nnnn
+ f.close()
+ return int(line.split()[1])
+
+ @wrap_exceptions
+ def get_process_uid(self):
+ if self.pid == 0:
+ return 0
+ f = open("/proc/%s/status" % self.pid)
+ for line in f:
+ if line.startswith('Uid:'):
+ # Uid line provides 4 values which stand for real,
+ # effective, saved set, and file system UIDs.
+ # We want to provide real UID only.
+ f.close()
+ return int(line.split()[1])
+
+ @wrap_exceptions
+ def get_process_gid(self):
+ if self.pid == 0:
+ return 0
+ f = open("/proc/%s/status" % self.pid)
+ for line in f:
+ if line.startswith('Gid:'):
+ # Uid line provides 4 values which stand for real,
+ # effective, saved set, and file system GIDs.
+ # We want to provide real GID only.
+ f.close()
+ return int(line.split()[1])
+
+ @staticmethod
+ def _decode_address(addr, family):
+ """Accept an "ip:port" address as displayed in /proc/net/*
+ and convert it into a human readable form, like:
+
+ "0500000A:0016" -> ("10.0.0.5", 22)
+ "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)
+
+ The IPv4 address portion is a little-endian four-byte hexadecimal
+ number; that is, the least significant byte is listed first,
+ so we need to reverse the order of the bytes to convert it
+ to an IP address.
+ The port is represented as a two-byte hexadecimal number.
+
+ Reference:
+ http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html
+ """
+ ip, port = addr.split(':')
+ port = int(port, 16)
+ if sys.version_info >= (3,):
+ ip = ip.encode('ascii')
+ # this usually refers to a local socket in listen mode with
+ # no end-points connected
+ if not port:
+ return ()
+ if family == socket.AF_INET:
+ ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1])
+ else: # IPv6
+ # old version - let's keep it, just in case...
+ #ip = ip.decode('hex')
+ #return socket.inet_ntop(socket.AF_INET6,
+ # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4)))
+ ip = base64.b16decode(ip)
+ ip = socket.inet_ntop(socket.AF_INET6,
+ struct.pack('>4I', *struct.unpack('<4I', ip)))
+ return (ip, port)
+
+PlatformProcess = LinuxProcess
+
« no previous file with comments | « third_party/psutil/psutil/_psbsd.py ('k') | third_party/psutil/psutil/_psmswindows.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698