
Move Process and SharedMemory into the base namespace (most changes). Review URL: http://codereview.chromium.org/10895 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5446 0039d316-1c4b-4281-b951-d872f2087c98
328 lines
12 KiB
C++
328 lines
12 KiB
C++
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// This file/namespace contains utility functions for enumerating, ending and
|
|
// computing statistics of processes.
|
|
|
|
#ifndef BASE_PROCESS_UTIL_H_
|
|
#define BASE_PROCESS_UTIL_H_
|
|
|
|
#include "base/basictypes.h"
|
|
|
|
#if defined(OS_WIN)
|
|
#include <windows.h>
|
|
#include <tlhelp32.h>
|
|
#elif defined(OS_LINUX)
|
|
#include <dirent.h>
|
|
#include <limits.h>
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
#include <string>
|
|
|
|
#include "base/command_line.h"
|
|
#include "base/process.h"
|
|
|
|
#if defined(OS_WIN)
|
|
typedef PROCESSENTRY32 ProcessEntry;
|
|
typedef IO_COUNTERS IoCounters;
|
|
#elif defined(OS_POSIX)
|
|
struct ProcessEntry {
|
|
int pid;
|
|
int ppid;
|
|
char szExeFile[NAME_MAX+1];
|
|
};
|
|
|
|
struct IoCounters {
|
|
unsigned long long ReadOperationCount;
|
|
unsigned long long WriteOperationCount;
|
|
unsigned long long OtherOperationCount;
|
|
unsigned long long ReadTransferCount;
|
|
unsigned long long WriteTransferCount;
|
|
unsigned long long OtherTransferCount;
|
|
};
|
|
#endif
|
|
|
|
namespace base {
|
|
|
|
// A minimalistic but hopefully cross-platform set of exit codes.
|
|
// Do not change the enumeration values or you will break third-party
|
|
// installers.
|
|
enum {
|
|
PROCESS_END_NORMAL_TERMINATON = 0,
|
|
PROCESS_END_KILLED_BY_USER = 1,
|
|
PROCESS_END_PROCESS_WAS_HUNG = 2
|
|
};
|
|
|
|
// Returns the id of the current process.
|
|
int GetCurrentProcId();
|
|
|
|
// Returns the ProcessHandle of the current process.
|
|
ProcessHandle GetCurrentProcessHandle();
|
|
|
|
// Returns the unique ID for the specified process. This is functionally the
|
|
// same as Windows' GetProcessId(), but works on versions of Windows before
|
|
// Win XP SP1 as well.
|
|
int GetProcId(ProcessHandle process);
|
|
|
|
#if defined(OS_WIN)
|
|
// Runs the given application name with the given command line. Normally, the
|
|
// first command line argument should be the path to the process, and don't
|
|
// forget to quote it.
|
|
//
|
|
// If wait is true, it will block and wait for the other process to finish,
|
|
// otherwise, it will just continue asynchronously.
|
|
//
|
|
// Example (including literal quotes)
|
|
// cmdline = "c:\windows\explorer.exe" -foo "c:\bar\"
|
|
//
|
|
// If process_handle is non-NULL, the process handle of the launched app will be
|
|
// stored there on a successful launch.
|
|
// NOTE: In this case, the caller is responsible for closing the handle so
|
|
// that it doesn't leak!
|
|
bool LaunchApp(const std::wstring& cmdline,
|
|
bool wait, bool start_hidden, ProcessHandle* process_handle);
|
|
#elif defined(OS_POSIX)
|
|
// Runs the application specified in argv[0] with the command line argv.
|
|
// Both the elements of argv and argv itself must be terminated with a null
|
|
// byte.
|
|
//
|
|
// As above, if wait is true, execute synchronously. The pid will be stored
|
|
// in process_handle if that pointer is non-null.
|
|
//
|
|
// Note that the first argument in argv must point to the filename,
|
|
// and must be fully specified.
|
|
bool LaunchApp(const std::vector<std::string>& argv,
|
|
bool wait, ProcessHandle* process_handle);
|
|
#endif
|
|
|
|
// Execute the application specified by cl. This function delegates to one
|
|
// of the above two platform-specific functions.
|
|
bool LaunchApp(const CommandLine& cl,
|
|
bool wait, bool start_hidden, ProcessHandle* process_handle);
|
|
|
|
// Used to filter processes by process ID.
|
|
class ProcessFilter {
|
|
public:
|
|
// Returns true to indicate set-inclusion and false otherwise. This method
|
|
// should not have side-effects and should be idempotent.
|
|
virtual bool Includes(uint32 pid, uint32 parent_pid) const = 0;
|
|
virtual ~ProcessFilter() { }
|
|
};
|
|
|
|
// Returns the number of processes on the machine that are running from the
|
|
// given executable name. If filter is non-null, then only processes selected
|
|
// by the filter will be counted.
|
|
int GetProcessCount(const std::wstring& executable_name,
|
|
const ProcessFilter* filter);
|
|
|
|
// Attempts to kill all the processes on the current machine that were launched
|
|
// from the given executable name, ending them with the given exit code. If
|
|
// filter is non-null, then only processes selected by the filter are killed.
|
|
// Returns false if all processes were able to be killed off, false if at least
|
|
// one couldn't be killed.
|
|
bool KillProcesses(const std::wstring& executable_name, int exit_code,
|
|
const ProcessFilter* filter);
|
|
|
|
// Attempts to kill the process identified by the given process
|
|
// entry structure, giving it the specified exit code. If |wait| is true, wait
|
|
// for the process to be actually terminated before returning.
|
|
// Returns true if this is successful, false otherwise.
|
|
bool KillProcess(int process_id, int exit_code, bool wait);
|
|
|
|
// Get the termination status (exit code) of the process and return true if the
|
|
// status indicates the process crashed. It is an error to call this if the
|
|
// process hasn't terminated yet.
|
|
bool DidProcessCrash(ProcessHandle handle);
|
|
|
|
// Wait for all the processes based on the named executable to exit. If filter
|
|
// is non-null, then only processes selected by the filter are waited on.
|
|
// Returns after all processes have exited or wait_milliseconds have expired.
|
|
// Returns true if all the processes exited, false otherwise.
|
|
bool WaitForProcessesToExit(const std::wstring& executable_name,
|
|
int wait_milliseconds,
|
|
const ProcessFilter* filter);
|
|
|
|
// Wait for a single process to exit. Return true if it exited cleanly within
|
|
// the given time limit.
|
|
bool WaitForSingleProcess(ProcessHandle handle,
|
|
int wait_milliseconds);
|
|
|
|
// Waits a certain amount of time (can be 0) for all the processes with a given
|
|
// executable name to exit, then kills off any of them that are still around.
|
|
// If filter is non-null, then only processes selected by the filter are waited
|
|
// on. Killed processes are ended with the given exit code. Returns false if
|
|
// any processes needed to be killed, true if they all exited cleanly within
|
|
// the wait_milliseconds delay.
|
|
bool CleanupProcesses(const std::wstring& executable_name,
|
|
int wait_milliseconds,
|
|
int exit_code,
|
|
const ProcessFilter* filter);
|
|
|
|
// This class provides a way to iterate through the list of processes
|
|
// on the current machine that were started from the given executable
|
|
// name. To use, create an instance and then call NextProcessEntry()
|
|
// until it returns false.
|
|
class NamedProcessIterator {
|
|
public:
|
|
NamedProcessIterator(const std::wstring& executable_name,
|
|
const ProcessFilter* filter);
|
|
~NamedProcessIterator();
|
|
|
|
// If there's another process that matches the given executable name,
|
|
// returns a const pointer to the corresponding PROCESSENTRY32.
|
|
// If there are no more matching processes, returns NULL.
|
|
// The returned pointer will remain valid until NextProcessEntry()
|
|
// is called again or this NamedProcessIterator goes out of scope.
|
|
const ProcessEntry* NextProcessEntry();
|
|
|
|
private:
|
|
// Determines whether there's another process (regardless of executable)
|
|
// left in the list of all processes. Returns true and sets entry_ to
|
|
// that process's info if there is one, false otherwise.
|
|
bool CheckForNextProcess();
|
|
|
|
bool IncludeEntry();
|
|
|
|
// Initializes a PROCESSENTRY32 data structure so that it's ready for
|
|
// use with Process32First/Process32Next.
|
|
void InitProcessEntry(ProcessEntry* entry);
|
|
|
|
std::wstring executable_name_;
|
|
|
|
#if defined(OS_WIN)
|
|
HANDLE snapshot_;
|
|
bool started_iteration_;
|
|
#elif defined(OS_LINUX)
|
|
DIR *procfs_dir_;
|
|
#elif defined(OS_MACOSX)
|
|
// probably kvm_t *kvmd_;
|
|
#endif
|
|
|
|
ProcessEntry entry_;
|
|
const ProcessFilter* filter_;
|
|
|
|
DISALLOW_EVIL_CONSTRUCTORS(NamedProcessIterator);
|
|
};
|
|
|
|
// Working Set (resident) memory usage broken down by
|
|
// priv (private): These pages (kbytes) cannot be shared with any other process.
|
|
// shareable: These pages (kbytes) can be shared with other processes under
|
|
// the right circumstances.
|
|
// shared : These pages (kbytes) are currently shared with at least one
|
|
// other process.
|
|
struct WorkingSetKBytes {
|
|
size_t priv;
|
|
size_t shareable;
|
|
size_t shared;
|
|
};
|
|
|
|
// Committed (resident + paged) memory usage broken down by
|
|
// private: These pages cannot be shared with any other process.
|
|
// mapped: These pages are mapped into the view of a section (backed by
|
|
// pagefile.sys)
|
|
// image: These pages are mapped into the view of an image section (backed by
|
|
// file system)
|
|
struct CommittedKBytes {
|
|
size_t priv;
|
|
size_t mapped;
|
|
size_t image;
|
|
};
|
|
|
|
// Free memory (Megabytes marked as free) in the 2G process address space.
|
|
// total : total amount in megabytes marked as free. Maximum value is 2048.
|
|
// largest : size of the largest contiguous amount of memory found. It is
|
|
// always smaller or equal to FreeMBytes::total.
|
|
// largest_ptr: starting address of the largest memory block.
|
|
struct FreeMBytes {
|
|
size_t total;
|
|
size_t largest;
|
|
void* largest_ptr;
|
|
};
|
|
|
|
// Provides performance metrics for a specified process (CPU usage, memory and
|
|
// IO counters). To use it, invoke CreateProcessMetrics() to get an instance
|
|
// for a specific process, then access the information with the different get
|
|
// methods.
|
|
class ProcessMetrics {
|
|
public:
|
|
// Creates a ProcessMetrics for the specified process.
|
|
// The caller owns the returned object.
|
|
static ProcessMetrics* CreateProcessMetrics(ProcessHandle process);
|
|
|
|
~ProcessMetrics();
|
|
|
|
// Returns the current space allocated for the pagefile, in bytes (these pages
|
|
// may or may not be in memory).
|
|
size_t GetPagefileUsage();
|
|
// Returns the peak space allocated for the pagefile, in bytes.
|
|
size_t GetPeakPagefileUsage();
|
|
// Returns the current working set size, in bytes.
|
|
size_t GetWorkingSetSize();
|
|
// Returns private usage, in bytes. Private bytes is the amount
|
|
// of memory currently allocated to a process that cannot be shared.
|
|
// Note: returns 0 on unsupported OSes: prior to XP SP2.
|
|
size_t GetPrivateBytes();
|
|
// Fills a CommittedKBytes with both resident and paged
|
|
// memory usage as per definition of CommittedBytes.
|
|
void GetCommittedKBytes(CommittedKBytes* usage);
|
|
// Fills a WorkingSetKBytes containing resident private and shared memory
|
|
// usage in bytes, as per definition of WorkingSetBytes.
|
|
bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage);
|
|
|
|
// Computes the current process available memory for allocation.
|
|
// It does a linear scan of the address space querying each memory region
|
|
// for its free (unallocated) status. It is useful for estimating the memory
|
|
// load and fragmentation.
|
|
bool CalculateFreeMemory(FreeMBytes* free);
|
|
|
|
// Returns the CPU usage in percent since the last time this method was
|
|
// called. The first time this method is called it returns 0 and will return
|
|
// the actual CPU info on subsequent calls.
|
|
// Note that on multi-processor machines, the CPU usage value is for all
|
|
// CPUs. So if you have 2 CPUs and your process is using all the cycles
|
|
// of 1 CPU and not the other CPU, this method returns 50.
|
|
int GetCPUUsage();
|
|
|
|
// Retrieves accounting information for all I/O operations performed by the
|
|
// process.
|
|
// If IO information is retrieved successfully, the function returns true
|
|
// and fills in the IO_COUNTERS passed in. The function returns false
|
|
// otherwise.
|
|
bool GetIOCounters(IoCounters* io_counters);
|
|
|
|
private:
|
|
explicit ProcessMetrics(ProcessHandle process);
|
|
|
|
ProcessHandle process_;
|
|
|
|
int processor_count_;
|
|
|
|
// Used to store the previous times so we can compute the CPU usage.
|
|
int64 last_time_;
|
|
int64 last_system_time_;
|
|
|
|
DISALLOW_EVIL_CONSTRUCTORS(ProcessMetrics);
|
|
};
|
|
|
|
// Enables low fragmentation heap (LFH) for every heaps of this process. This
|
|
// won't have any effect on heaps created after this function call. It will not
|
|
// modify data allocated in the heaps before calling this function. So it is
|
|
// better to call this function early in initialization and again before
|
|
// entering the main loop.
|
|
// Note: Returns true on Windows 2000 without doing anything.
|
|
bool EnableLowFragmentationHeap();
|
|
|
|
// Enable 'terminate on heap corruption' flag. Helps protect against heap
|
|
// overflow. Has no effect if the OS doesn't provide the necessary facility.
|
|
void EnableTerminationOnHeapCorruption();
|
|
|
|
// If supported on the platform, and the user has sufficent rights, increase
|
|
// the current process's scheduling priority to a high priority.
|
|
void RaiseProcessToHighPriority();
|
|
|
|
} // namespace base
|
|
|
|
#endif // BASE_PROCESS_UTIL_H_
|