/// <summary>
        /// Gets information about process or thread(s)
        /// </summary>
        /// <param name="pid">The PID of the process. If PID is 0, this will return all processes</param>
        /// <param name="threads">Whether to include thread information.</param>
        /// <param name="count">The number of kinfo_proc entries returned.</param>
        public static unsafe kinfo_proc *GetProcInfo(int pid, bool threads, out int count)
        {
            Span <int> sysctlName = stackalloc int[4];

            if (pid == 0)
            {
                // get all processes
                sysctlName[3] = 0;
                sysctlName[2] = KERN_PROC_PROC;
            }
            else
            {
                // get specific process, possibly with threads
                sysctlName[3] = pid;
                sysctlName[2] = KERN_PROC_PID | (threads ? KERN_PROC_INC_THREAD : 0);
            }
            sysctlName[1] = KERN_PROC;
            sysctlName[0] = CTL_KERN;

            byte *pBuffer     = null;
            int   bytesLength = 0;

            Interop.Sys.Sysctl(sysctlName, ref pBuffer, ref bytesLength);

            kinfo_proc *kinfo = (kinfo_proc *)pBuffer;

            Debug.Assert(kinfo->ki_structsize == sizeof(kinfo_proc));

            count = (int)bytesLength / sizeof(kinfo_proc);

            // Buffer ownership transferred to the caller
            return(kinfo);
        }
示例#2
0
        /// <summary>
        /// Gets the process information for a given process
        /// </summary>
        /// <param name="pid">The PID (process ID) of the process</param>
        /// <returns>
        /// Returns a valid ProcessInfo struct for valid processes that the caller
        /// has permission to access; otherwise, returns null
        /// </returns>
        static public unsafe ProcessInfo GetProcessInfoById(int pid)
        {
            kinfo_proc *kinfo = null;
            int         count;
            ProcessInfo info;

            // Negative PIDs are invalid
            if (pid < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(pid));
            }

            try
            {
                kinfo = GetProcInfo(pid, true, out count);
                if (kinfo == null || count < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(pid));
                }

                Span <kinfo_proc> process = new Span <kinfo_proc>(kinfo, count);

                // Get the process information for the specified pid
                info = new ProcessInfo();

                info.ProcessName  = Marshal.PtrToStringAnsi((IntPtr)kinfo->ki_comm);
                info.BasePriority = kinfo->ki_nice;
                info.VirtualBytes = (long)kinfo->ki_size;
                info.WorkingSet   = kinfo->ki_rssize;
                info.SessionId    = kinfo->ki_sid;

                for (int i = 0; i < process.Length; i++)
                {
                    var ti = new ThreadInfo()
                    {
                        _processId    = pid,
                        _threadId     = (ulong)process[i].ki_tid,
                        _basePriority = process[i].ki_nice,
                        _startAddress = (IntPtr)process[i].ki_tdaddr
                    };
                    info._threadInfoList.Add(ti);
                }
            }
            finally
            {
                Marshal.FreeHGlobal((IntPtr)kinfo);
            }

            return(info);
        }
示例#3
0
        /// <summary>
        /// Gets information about process or thread(s)
        /// </summary>
        /// <param name="pid">The PID of the process. If PID is 0, this will return all processes</param>
        public static unsafe kinfo_proc *GetProcInfo(int pid, bool threads, out int count)
        {
            Span <int>  sysctlName  = stackalloc int[4];
            int         bytesLength = 0;
            byte *      pBuffer     = null;
            kinfo_proc *kinfo       = null;
            int         ret;

            count = -1;

            if (pid == 0)
            {
                // get all processes
                sysctlName[3] = 0;
                sysctlName[2] = KERN_PROC_PROC;
            }
            else
            {
                // get specific process, possibly with threads
                sysctlName[3] = pid;
                sysctlName[2] = KERN_PROC_PID | (threads ? KERN_PROC_INC_THREAD : 0);
            }
            sysctlName[1] = KERN_PROC;
            sysctlName[0] = CTL_KERN;

            try
            {
                ret = Interop.Sys.Sysctl(sysctlName, ref pBuffer, ref bytesLength);
                if (ret != 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pid));
                }

                kinfo = (kinfo_proc *)pBuffer;
                if (kinfo->ki_structsize != sizeof(kinfo_proc))
                {
                    // failed consistency check
                    throw new ArgumentOutOfRangeException(nameof(pid));
                }

                count = (int)bytesLength / sizeof(kinfo_proc);
            }
            catch
            {
                Marshal.FreeHGlobal((IntPtr)pBuffer);
                throw;
            }

            return(kinfo);
        }
示例#4
0
        /// <summary>
        /// Gets the process information for a given process
        /// </summary>
        /// <param name="pid">The PID (process ID) of the process</param>
        /// <param name="tid">The TID (thread ID) of the process</param>
        /// <returns>
        /// Returns basic info about thread. If tis is 0, it will return
        /// info for process e.g. main thread.
        /// </returns>
        public static unsafe proc_stats GetThreadInfo(int pid, int tid)
        {
            proc_stats  ret  = default;
            kinfo_proc *info = null;
            int         count;

            try
            {
                info = GetProcInfo(pid, (tid != 0), out count);
                if (info != null && count >= 1)
                {
                    if (tid == 0)
                    {
                        ret.startTime  = (int)info->ki_start.tv_sec;
                        ret.nice       = info->ki_nice;
                        ret.userTime   = (ulong)info->ki_rusage.ru_utime.tv_sec * SecondsToNanoseconds + (ulong)info->ki_rusage.ru_utime.tv_usec;
                        ret.systemTime = (ulong)info->ki_rusage.ru_stime.tv_sec * SecondsToNanoseconds + (ulong)info->ki_rusage.ru_stime.tv_usec;
                    }
                    else
                    {
                        var list = new ReadOnlySpan <kinfo_proc>(info, count);
                        for (int i = 0; i < list.Length; i++)
                        {
                            if (list[i].ki_tid == tid)
                            {
                                ret.startTime  = (int)list[i].ki_start.tv_sec;
                                ret.nice       = list[i].ki_nice;
                                ret.userTime   = (ulong)list[i].ki_rusage.ru_utime.tv_sec * SecondsToNanoseconds + (ulong)list[i].ki_rusage.ru_utime.tv_usec;
                                ret.systemTime = (ulong)list[i].ki_rusage.ru_stime.tv_sec * SecondsToNanoseconds + (ulong)list[i].ki_rusage.ru_stime.tv_usec;
                                break;
                            }
                        }
                    }
                }
            }
            finally
            {
                Marshal.FreeHGlobal((IntPtr)info);
            }

            return(ret);
        }
示例#5
0
        /// <summary>
        /// Queries the OS for the list of all running processes and returns the PID for each
        /// </summary>
        /// <returns>Returns a list of PIDs corresponding to all running processes</returns>
        internal static unsafe int[] ListAllPids()
        {
            int numProcesses = 0;

            int[]       pids;
            kinfo_proc *entries = null;
            int         idx;

            try
            {
                entries = GetProcInfo(0, false, out numProcesses);
                if (entries == null || numProcesses <= 0)
                {
                    throw new Win32Exception(SR.CantGetAllPids);
                }

                Span <kinfo_proc> list = new Span <kinfo_proc>(entries, numProcesses);
                pids = new int[numProcesses];
                idx  = 0;
                // walk through process list and skip kernel threads
                for (int i = 0; i < list.Length; i++)
                {
                    if (list[i].ki_ppid == 0)
                    {
                        // skip kernel threads
                        numProcesses -= 1;
                    }
                    else
                    {
                        pids[idx] = list[i].ki_pid;
                        idx      += 1;
                    }
                }
                // Remove extra elements
                Array.Resize <int>(ref pids, numProcesses);
            }
            finally
            {
                Marshal.FreeHGlobal((IntPtr)entries);
            }
            return(pids);
        }
示例#6
0
        /// <summary>
        /// Queries the OS for the list of all running processes and returns the PID for each
        /// </summary>
        /// <returns>Returns a list of PIDs corresponding to all running processes</returns>
        internal static unsafe int[] ListAllPids()
        {
            kinfo_proc *entries = GetProcInfo(0, false, out int numProcesses);

            try
            {
                if (numProcesses <= 0)
                {
                    throw new Win32Exception(SR.CantGetAllPids);
                }

                var list = new ReadOnlySpan <kinfo_proc>(entries, numProcesses);
                var pids = new int[numProcesses];

                // walk through process list and skip kernel threads
                int idx = 0;
                for (int i = 0; i < list.Length; i++)
                {
                    if (list[i].ki_ppid == 0)
                    {
                        // skip kernel threads
                        numProcesses -= 1;
                    }
                    else
                    {
                        pids[idx] = list[i].ki_pid;
                        idx      += 1;
                    }
                }

                // Remove extra elements
                Array.Resize <int>(ref pids, numProcesses);
                return(pids);
            }
            finally
            {
                NativeMemory.Free(entries);
            }
        }