About the Pid of the Process

About the pid of the process

This is determined by the Operating System.

In general, they are usually sequentially assigned by the OS. However, this behavior is not something to base decisions upon, since most operating system specifications state that the process ID allocation is not deterministic (ie: it could be random, and could change in a future version, etc).

How Do You Determine The PID of the Parent of a Process

You should pass self() to the child as one of the arguments to the entry function.

spawn_link(?MODULE, child, [self()]).

Get the PID of a process launched in the same command line

You can do this

./myscript.sh & echo $! >> log.pid

Then you will store your PID in a file. But perhaps you need to store also the date and hour.

./sleep.sh & echo $! `date` >> log.pid

Example

$ more sleep.sh
sleep 10
$ ./sleep.sh & echo $! `date` >> log.pid
[1] 9588
$ ./sleep.sh & echo $! `date` >> log.pid
[2] 9640
$ ./sleep.sh & echo $! `date` >> log.pid
[3] 9646
$ cat log.pid
9588 Wed Jul 8 14:03:19 CEST 2020
9640 Wed Jul 8 14:03:22 CEST 2020
9646 Wed Jul 8 14:03:23 CEST 2020

Get pid from brother process

The parent should fork three times, the children should not fork. This way, the parent will know the pids of all three children.

After the fork, you'll need some kind of separate communication channel by which the parent can communicate these pids to all children. A simple way would be to open a pipe (see pipe(2)) before forking each child, so the child inherits the pipe's file descriptor (at least the read end) and the parent keeps the write end. Then have the parent send the three pids down each pipe and close it.

Example code (long, but that's the nature of C):

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

#define NUM_CHILDREN 3

/* Entry point for the child processes */
int child_main(int pipe_read_end) {
pid_t my_pid = getpid();

/* Read child pids from pipe */
int child_pids[NUM_CHILDREN];
unsigned int bytes_read = 0;
while (bytes_read < sizeof(child_pids)) {
ssize_t result = read(pipe_read_end, ((unsigned char *) child_pids) + bytes_read, sizeof(child_pids) - bytes_read);
if (result < 0) {
perror("error reading from pipe");
return 1;
} else if (result == 0) {
fprintf(stderr, "unexpected end of file\n");
return 1;
} else {
bytes_read += result;
}
}
close(pipe_read_end);

/* Do something useful with these child pids */
for (int i = 0; i < NUM_CHILDREN; i++) {
printf("Child %d received sibling pid %d\n", my_pid, child_pids[i]);
}

return 0;
}

/* Entry point for the parent process. */
int main() {
int child_pids[NUM_CHILDREN];
int pipe_write_ends[NUM_CHILDREN];
for (int i = 0; i < NUM_CHILDREN; i++) {
/* Create the pipe for child i */
int pipefd[2];
if (pipe(pipefd)) {
perror("error creating pipe");
return 1;
}
int pipe_read_end = pipefd[0];
int pipe_write_end = pipefd[1];

/* Fork child i */
pid_t child_pid = fork();
if (child_pid < 0) {
perror("error forking");
return 1;
} else if (child_pid == 0) {
printf("Child %d was forked\n", getpid());
close(pipe_write_end);
return child_main(pipe_read_end);
} else {
printf("Parent forked child %d\n", child_pid);
close(pipe_read_end);
pipe_write_ends[i] = pipe_write_end;
child_pids[i] = child_pid;
}
}

/* Send pids down the pipes for each child */
for (int i = 0; i < NUM_CHILDREN; i++) {
unsigned int bytes_written = 0;
while (bytes_written < sizeof(child_pids)) {
ssize_t result = write(pipe_write_ends[i], ((unsigned char *) child_pids) + bytes_written, sizeof(child_pids) - bytes_written);
if (result < 0) {
perror("error writing to pipe");
return 1;
} else {
bytes_written += result;
}
}
close(pipe_write_ends[i]);
}

/* Wait for children to exit */
for (int i = 0; i < NUM_CHILDREN; i++) {
if (waitpid(child_pids[i], 0, 0) < 0) {
perror("error waiting for child");
return 1;
}
}
}

As @PSkocik points out in their answer, you should probably not be doing this. Pids can be reused by the OS, so there's no way for the children to know that their sibling pids still actually refer to their siblings; only the parent can be sure, because it has to wait for each pid before it can be reused.

However, this same mechanism can be used for other forms of IPC (inter-process communication); you could, for example, use it to create pipes between the children directly.

Finding the PID of a process launched by exec() or system() in C program

The exec* family of functions do not create new processes, instead they replace the execution context of the process they are called from, with the execution context of their target executable. The PID is maintained when this occurs.

#include <unistd.h>
#include <stdio.h>

int main(void) {
/* Normal execution */
puts("Hello");

/* Our programs contents get "replaced" by ls */
execlp("ls", "-l", NULL);

/* We never get here */
puts("World!");
}

fork, on the other hand, creates a new child process, which of course has its own PID. This child process carries on executing a copy of the same execution context it was spawned from; you can consider the execution to be "split" as soon as fork is called. fork returns 0 in the child process, and the PID of the child process in the parent (our original process).

The idea is to fork, and then use exec* to replace the execution context of the child process.

#include <unistd.h>
#include <stdio.h>

int main(void) {
pid_t pid;
/* Normal execution */
puts("Hello");

/* execution "splits" */
pid = fork();
if (pid == 0) {
/* Our child's execution context get "replaced" by ls */
execlp("ls", "-l", NULL);
} else {
/* still in the parent */
printf("Child PID is: %d\n", (int) pid);
}

/* We only get here in the parent */
puts("World!");
}

system is a wrapper around fork, exec* and and waitpid that blocks the calling process until the child process finishes its execution. The child's PID is not reported, because by the time parent can "act" again, the PID of the child is meaningless.


Error handling omitted for clarity of examples, but you should handle errors for fork, exec*, and wait* functions.

Windows Ruby get PID from process name

The sys-proctable gem can do that, here is a minimal example for getting the PID of the ruby.exe process on the system:

require 'sys/proctable'

def get_process_id(name)
Sys::ProcTable.ps.detect{|p| p.name == name}&.pid
end

puts get_process_id("ruby.exe")

That doesn't guarantee you will find the parent process tho, you will instead get the process with the lowest PID.

To actually find the "root process", you need to further select processes by checking if their parent process is either non-existent or a different process:

require 'sys/proctable'

def get_parent_process_id(name)
# generate a hash mapping pid -> process info
processes = Sys::ProcTable.ps.map{|p| [p.pid, p]}.to_h

# find the first matching process that has either no parent or a parent
# that doesn't match the process name we're looking for
processes.values.each do |p|
next if p.name != name

if processes[p.ppid].nil? || processes[p.ppid].name != name
return p.pid
end
end

nil
end

puts get_parent_process_id("chrome.exe")

PID returned by spawn differs from Process.pid of the child process

Looks like the background job operator (&) is causing the intermediate process 1886789. When I remove the background job operator, I get the following output:

Hi parent
93185
Start pid 93185
Bye parent
End pid 93185


Related Topics



Leave a reply



Submit