How to get the pid of another process in c? - c

I am using the getpid and get the pid of current process. Now I am try to get the pid of other process using process name. How to get the other process pid?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
printf("My pid:%d\n", getpid());
return 0;
}

You could use popen() with the command program pidof to get the pid of any program.
Like this:
char line[total_length];
FILE * command = popen("pidof ...","r");
fgets(line,total_length,command);
pid_t pid = strtoul(line,NULL,10);
pclose(command);
Edit:
Please see: How to get the PID of a process in Linux in C

1: The most common way, used by daemons. Store the pid number in a file/files. Then other processes can easily find them.
2: Portable way, spawn a child process to executes ps with a pipe. Then you can parse the text output and find your target process.
3: Non-portable way, parse the /proc/ filesystem
Often, 1 is combined with 2 or 3, in order to verify that the pid is correct.

Related

How do I consistently find the PID of a program OR how do I send the kill shortcut to my terminal from a C script?

I'm answering my own question here because all of the other threads talking about this gave generally inefficient solutions to this problem[refer to title].
The most logical way to find the PID of a program is with getpid. However for some reason getpid command always gives you the PID that is two numbers behind the actual program ID it's about to be assigned. I'm sure someone more familiar with the linux kernel will be sure to explain why I'm an idiot in the comments below, so the reasoning for the -2 pid is probably down there.
Anyway, here's a reverse engineered c script(from MTU) that gives you the PID of the program.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
void main(void)
{
pid_t pid;
char fetch[50];
pid = getpid();
int pid2=pid+2;
sprintf(fetch, "echo hello world! my PID is %d", pid2);
system(fetch);
}
However for some reason getpid command always gives you the PID that is two numbers behind the actual program ID it's about to be assigned.
Well, getpid returns the PID of the current process.
How can it return the PID of a new process that doesn't exist yet? How could it possibly know?
The current process has a process ID. When you call system, it creates a child process, with its own process ID. Presumably the child process then creates another child to execute the command you passed to system.
By default the first child's PID will be the current process PID + 1. And the second child's PID will be the current process PID + 2. However, if either of those IDs are already in use (or you hit the maximum value of a pid_t and wrap around), this brittle logic will break completely.
If you want to get a child process' PID, call fork directly:
pid_t childpid = fork();
if (childpid < 0) {
perror("failed to fork");
exit(1);
}
if (childpid == 0) {
/* this path executes in the child process */
exec_command_in_child();
} else {
/* this path executes in the parent */
wait_or_kill_or_something(childpid);
}

fork() and wait() in C

I am trying to learn the fork() and wait() system calls. If I run this code :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main (){
printf("Hi, I am the parent with pid %d \n ",getpid());
int rc = fork();
printf("Fork returned : %d \n ",rc);
printf("I am the process with pid %d \n ",getpid());
wait(NULL);
return 0;
}
I get the output as expected on the terminal :
Hi, I am the parent with pid 3639
Fork returned : 3640
I am the process with pid 3639
Fork returned : 0
I am the process with pid 3640
However , If I remove wait(NULL) , I get a strange output on the terminal :
Hi, I am the parent with pid 3715
Fork returned : 3716
I am the process with pid 3715
John#John-VirtualBox:~/Fork5$ Fork returned : 0
I am the process with pid 3716
I totally understand that , we use wait() to make the parent process waits for the child to end executiion so that we can remove it from the process table and deallocate its PID . But here , if I remove the wait , we see that the terminal is called again :
John#John-VirtualBox:~/Fork5$ Fork returned : 0
I am the process with pid 3716
And even it doesn't return again back . I don't understand what this have to do with the functionality of wait ? Or in other words , why wait will fix this issue ?
The sequence of events appears to be:
The shell is the parent process to your program. When it forks your program your program inherits the standard streams (to the terminal).
Your program forks a child process which also inherits the standard streams (to the terminal).
When your parent process terminates, the shell notices (because it is waiting) and issues a prompt to the terminal.
However, your program’s child has not yet terminated, so after the shell issues its prompt the child prints its output (and then terminates).
You will notice that the shell does not issue a second prompt after the child terminates. (The shell does not know anything about your child process.)
Order of output
The fact that you get complete output lines (instead of anything interleaved) is because the standard streams for all processes are in line oriented mode.
However, there is no guarantee of order between processes. The OS scheduler can order them any way it wants. Your child could have printed before the parent.
:O)

How does getpgid() work?

I'm trying to get the pid, the ppid and the pgid
and no matter what I do getpgid(pid) always gives me the pid.
At first, I was using it like this:
printf("PGID: %d", getpgid());
Then I realized, getpgid was taking a pid as argument so I did this:
printf("PGID: %d", getpgid(getpid()));
But this is still giving me the same number as the pid...
So I tried this:
pid_t pid;
pid = getpid();
printf("PGID: %d", getpgid(pid));
And this still doesn't work... Any idea why?
PS: I'm a beginner in c.
The process group leader is always the one that has pid == pgid, so perhaps you are making always the same test (on a process group leader) and this is the reason of getting always the same pgid as the pid of the process. When a process becomes a group leader, the kernel assigns it it's own pid as the pgid, so perhaps you are always getting that if you are checking in only one process. Bash uses process groups to distinguish background jobs and do job control, so every command you execute from a bash(1) shell will have a new process group and one of these processes (the only one if you only launched one process) will have the same the pgid and the pid of one of the processes of the job you are requesting.
The reason of this logic (to use the pid of the process group leader as the pgid) is to not have to deal with active process groups as no more groups than processed can be in the system... so when a new group id is needed the nearest process available is the own process that triggers the new process group creation, so assigning its own pid as pgid is no harmful.
For a simple example... just try the same program you used to demonstrate the pid and pgid values in a long pipe by piping them (you should try to print the output to stderr instead of stdout or all the outputs will get lost in the input buffer of the next process in the pipe):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pid = getpid();
fprintf(stderr, "pid=%d; pgid=%d\n", pid, getpgid(pid));
exit(EXIT_SUCCESS);
}
and then
$ testpgid | testpgid | testpgid
pid=3819; pgid=3819
pid=3820; pgid=3819
pid=3821; pgid=3819
$ testpgid | testpgid | testpgid
pid=3833; pgid=3833
pid=3835; pgid=3833
pid=3834; pgid=3833
getpid() returns the process ID of the current process.
When a process is running, the kernel schedules its runtime - especially it assigns a PID to it - such information is stored inside the kernel address space, in data structures (e.g. inside a task struct).
Thus, when a process calls the getpid() system call, the kernel just has to look in the task structure of the calling process.
It is a group ID of the process specified by pid.
Suppose if we consider pid as zero then the ID of the current process is used in it. getpgrp() and getpgid(0) are equivalent to each other.
e.g. pid_t getpgid(pid_t pid);

Determining if a process is a child or parent process (not using return value of fork)

How to write a programm to show whether it's a child or parent process after the fork() is used?
I need to find other way then checking the return value of fork() or getpid() function.
I know e.g. that process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child. How i can use for example that knowledge (or other child-parents differences) to determine my problem?
Thank you for your help!
Setup a signal handler for SIGCHLD in one of the processes and end the other one. If the SIGCHLD handler gets called you know the child died. If not the parent died.
Another (less distructive) way it to call wait(). If it returns ECHLD no child is around, thus the calling process is the child. If it blocks, at least one child is around, thus the calling process is the parent.
Or call waitpid() with PID of the other process. The same logic on the result as for wait() applies.
You could exploit the fact that the parent will be a process group leader (and thus its pid will be the same as its process group id) while the child will be a member of that process group and thus its pid will be different from the process group id:
#include <stdio.h>
#include <unistd.h>
main(int argc, char **argv) {
char *self = NULL;
fork(); /* looking at return value would be cheating */
int pid = getpid();
int pgid = getpgid(0);
if (pid == pgid)
self = "Parent";
else
self = "Child";
printf("%s pid = %d pgid = %d\n", self, pid, pgid);
}
Running yields:
$ ./pgid
Parent pid = 29400 pgid = 29400
Child pid = 29401 pgid = 29400
This does of course still use getpid() but not in the same way you describe above.
On Linux, you might also use proc(5). The process of pid 1234 is described by the directory /proc/1234/ and you could read sequentially and parse the /proc/1234/status pseudo-file to get all that information.
To understand a bit more, read the proc(5) man page, then type
cat /proc/self/status
cat /proc/$$/status
cat /proc/self/maps
cat /proc/$$/maps
in a terminal, and try to understand the output. You might parse it programmatically (e.g. with  FILE*f = fopen("/proc/1234/status","r"); then do some fgets or fscanf on f; then fclose(f);)

Doesn't vim 'fork' a shell to execute a command

I'm reading APUE about process groups. The book says,
In most job-control shells, this function(setpgid) is called after a fork to have the child set its own process group ID. One of these calls is redundant, but by doing both, we are guaranteed that the child is placed into its own process group before either process assumes that this has happened.
I wrote the following piece of code in order to verify my understanding. Error handling is omitted.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("process ID: %d\n", getpid());
printf("process group ID: %d\n", getpgrp());
exit(0);
}
output (run it directly into a shell):
process ID: 4388
process group ID: 4388
output (run inside of vim):
process ID: 4401
process group ID: 4400 // pid of vim (through ps)
Why do the results differ? Doesn't vim fork a shell to execute a command? If it does, what is the difference or in other words, why the process group ID not equal to process ID like the first output?
BTW, does fork always automatically set the process group ID of child process? I tried to print the process group ID of a child process before set it and it printed the process ID of the parent process.
Many thanks.
It looks like that the shell gives you a new pgid when it starts your command; and vim doesn't.

Resources