How to Get Process's Grandparent Id

How to get process's grandparent id

linux specific:

os.popen("ps -p %d -oppid=" % os.getppid()).read().strip()

Fetching parent process Id from child process

You should use the Native API and GetProcAddress to find the address of NtQueryInformationProcess.

typedef struct _PROCESS_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
ULONG_PTR AffinityMask;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
HANDLE InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
__in HANDLE ProcessHandle,
__in PROCESS_INFORMATION_CLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);

PROCESS_BASIC_INFORMATION basicInfo;

NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &basicInfo, sizeof(basicInfo), NULL);
// My parent PID (*) is in basicInfo.InheritedFromUniqueProcessId

To get the grandparent PID, open the parent process using the parent PID and call NtQueryInformationProcess again on the parent process.

Note * - Strictly speaking, the parent process (the process which created the child process) is not actually recorded. InheritedFromUniqueProcessId just gives you the process from which attributes were inherited. But this is very rarely a problem.

Alternatively, if you don't like the Native API, use CreateToolhelp32Snapshot with TH32CS_SNAPPROCESS, which gives you the required information, except that you'll have to search through the list.

Getting the parent id of a given process in Ruby

You can just remember it in a variable:

parent_pid = Process.pid

Process.fork do
child_pid = Process.pid
puts parent_pid, child_pid
# do stuff
exit
end

Process.wait

# 94791
# 94798

alternatively, if you need the information on the level of the parent process:

parent_pid = Process.pid

child_pid = Process.fork do
# do stuff
exit
end

Process.wait
puts parent_pid, child_pid

# 6361
# 6362

How to know if a process is a parent or a child

Process IDs: Child- and parent processes

All running programs have a unique process ID. The
process ID, a
non-negative integer, is the only identifier of a process that is
always unique. But, process IDs are reused.

As a process terminates its ID becomes available for reuse. Certain
systems delay reuse so that newly created processes are not confused
with old ones.

Certain IDs are "reserved" in the sense that they are being used by
system processes, such as the scheduler process. Another example is
the init process that always occupies PID 1. Depending on the system
the ID might be actively reserved.

Running the commands

> ps -eaf | head -n 5
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:49 ? 00:00:02 /sbin/init splash
root 2 0 0 11:49 ? 00:00:00 [kthreadd]
root 3 2 0 11:49 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 11:49 ? 00:00:00 [kworker/0:0H]

and

> pidof init
1

will allow you to independently verify this.1

In C we can use the following functions to get the process ID of the
calling process and the parent process ID of the calling process,

#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);

A process can create other processes. The created processes are called
"child processes" and we refer to the process that created them as
the "parent process".

Creating a new process using fork()

To create a child process we use the system call
fork()

#include <unistd.h>

pid_t fork(void);

The function is called once, by the parent process, but it returns
twice. The return value in the child process is 0, and the return
value in the parent process is the process ID of the new child.1

A process can have multiple child processes but there is no system
call for a process to get the process IDs of all of its children, so
the parent observes the return value of the child process and can use
these identifiers to manage them.

A process can only have a single parent process, which is always
obtainable by calling getppid.

The child is a copy of the parent, it gets a copy of the parent's
data space, heap and stack. They do not share these portions of
memory! 2

We will compile and execute the following code snippet to see how
this works,

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>

int main(void) {
int var = 42; // This variable is created on the stack
pid_t pid;

// Two processes are created here
// v~~~~~~~~~~|
if ((pid = fork()) < 0) {
perror("Fork failed");
} else if (pid == 0) { // <- Both processes continue executing here
// This variable gets copied
var++;

printf("This is the child process:\n"
"\t my pid=%d\n"
"\t parent pid=%d\n"
"\t var=%d\n", getpid(), getppid(), var);

} else {
printf("This is the parent process:\n"
"\t my pid=%d\n"
"\t child pid=%d\n"
"\t var=%d\n", getpid(), pid, var);

}

return 0;
}

We will see when we execute the program that there are no guarantees
as to which process gets to execute first. They may even operate
simultaneously, effectively interleaving their output. 3

$ # Standard compilation
$ gcc -std=c99 -Wall fork_example1.c -o fork_example1
$ # Sometimes the child executes in its entirety first
$ ./fork_example1
This is the child process:
my pid=26485
parent pid=26484
var=43
This is the parent process:
my pid=26484
child pid=26485
var=42
$ # and sometimes the parent executes in its entirety first
$ ./fork_example1
This is the parent process:
my pid=26461
child pid=26462
var=42
This is the child process:
my pid=26462
parent pid=26461
var=43
$ # At times the two might interleave
$ ./fork_example1
This is the parent process:
my pid=26455
This is the child process:
my pid=26456
parent pid=26455
var=43
child pid=26456
var=42

1 PID stands for Process ID and PPID stands for
Parent Process ID.

2 The process ID 0 is reserved for use by the kernel, so
it is not possible for 0 to be the process ID of a child.

3 Many systems do not perform a complete copy of these
memory segments and instead only creates a copy when either process
performs a write. Initially, the shared regions are marked by the
kernel as "read-only" and whenever a process tries to modify these
regions the kernel awards each process their own copy of that memory.

4 Standard out is buffered so it's not a perfect example.

How to display the pid of a parent process

You could just save the pid in grandparent.

int pid, status, status2;
int pppid = getpid();
pid = fork();
switch (pid) {
....
printf("My parent G has pid %d\n", pppid);
}

or save the pid of getppid() in parent. There is no "standard" way of getting "parent pid of parent pid" so it's just the same as getting pid of any other process. You could inspect /proc/<pid>/stat, something along:

pid_t getppid_of_pid(pid_t pid) {
intmax_t ret = -1;

char *buf;
int r = asprintf(&buf, "/proc/%jd/stat", (intmax_t)pid);
if (r == -1) goto asprintf_err;

FILE *f = fopen(buf, "r");
if (f == NULL) return fopen_err;

if (fscanf(f, "%*s %*s %*s %jd", &ret) != 1) return fscanf_err;

fscanf_err:
fclose(f);
fopen_err:
free(buf);
asprintf_err:
return ret;
}


...
printf("My Grandparent G has pid %jd\n", (intmax_t)getppid_of_pid(getppid()));

See man procfs for explanation of fields in /proc/../stat.

Get Parent process id from child process id using Golang

I don't think the go standard library allows you to do this, however, third-party packages such as mitchellh/go-ps provide more information.

Example:

import ps "github.com/mitchellh/go-ps"
...

list, err := ps.Processes()
if err != nil {
panic(err)
}
for _, p := range list {
log.Printf("Process %s with PID %d and PPID %d", p.Executable(), p.Pid(), p.PPid())
}

Output:

2019/06/12 09:13:04 Process com.apple.photom with PID 68663 and PPID 1
2019/06/12 09:13:04 Process CompileDaemon with PID 49896 and PPID 49895

You can also use ps.FindProcess(<pid>) to find a specific process and inspect its PPid

How to get parent process in .NET in managed way

This code provides a nice interface for finding the Parent process object and takes into account the possibility of multiple processes with the same name:

Usage:

Console.WriteLine("ParentPid: " + Process.GetProcessById(6972).Parent().Id);

Code:

public static class ProcessExtensions {
private static string FindIndexedProcessName(int pid) {
var processName = Process.GetProcessById(pid).ProcessName;
var processesByName = Process.GetProcessesByName(processName);
string processIndexdName = null;

for (var index = 0; index < processesByName.Length; index++) {
processIndexdName = index == 0 ? processName : processName + "#" + index;
var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
if ((int) processId.NextValue() == pid) {
return processIndexdName;
}
}

return processIndexdName;
}

private static Process FindPidFromIndexedProcessName(string indexedProcessName) {
var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
return Process.GetProcessById((int) parentId.NextValue());
}

public static Process Parent(this Process process) {
return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
}
}


Related Topics



Leave a reply



Submit