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
How Do 2 or More Fork System Calls Work
Is There a Limit on Number of Tcp/Ip Connections Between MAChines on Linux
How to Enable Bash in Windows 10 Developer Preview
Using Jq to Fetch Key Value from JSON Output
How to Properly Set Java_Home in /Etc/Environment
Scp File from Local to Heroku Server
Rsync Over Ssh Preserve Ownership Only for Www-Data Owned Files
Can't Run Executable Linked with Libc
Diolan Dln-2 Spi Controller on X86_64 Platform
How to File Split at a Line Number
Find and Basename Not Playing Nicely