I have a piece of code to do execvp.
if (0 != child_pid) {
/* Parent Process */
printf("This is parent process: PID: %d\n",getpid());
return child_pid;
} else {
/* Child Process */
printf("This is child process: PID: %d\n",getpid());
printf("Parent process is: PPID: %d\n",getppid());
execvp(program,arg_list);
printf("Checking whether execvp fails/control reaches this line\n");
fprintf(stderr,"An Error occurred during execvp\n");
abort();
}
After getting the process id (printed via getpid()), i searched the /proc/$PID. But am not getting entry for this process. What does it mean?. Will /proc entries will get cleared once the process gets killed.?
/proc only contains entries for processes that currently exist. It sounds like your process has terminated and no longer exists by the time you go looking for it in /proc.
Related
I'm attempting to simulate a shell processing foreground commands but I'm running into trouble when it comes to reaping child processes. I spawn multiple processes using fork in the following code.
while (currCmdListNode != list_end(¤tPipeline->commands)) {
if (fork() == 0)
{
printf("Child created with pid %d \n", getpid());
currentCmd = list_entry(currCmdListNode, struct esh_command, elem);
execvp(currentCmd->argv[0], currentCmd->argv);
}
currCmdListNode = list_next(currCmdListNode);
}
Then, I try to reap all these processes from the parent process using the following code.
while((pid = waitpid(-1, &status, WUNTRACED)) > 0)
{
if (WIFEXITED(status))
{
printf("child %d terminated normally with exit status=%d\n", pid, WEXITSTATUS(status));
}
else
{
printf("child %d terminated abnormally\n", pid);
}
}
Let's say I run this code so that two child processes spawn from my initial fork. My reap functionality will return saying it reaped the first child. However, it will hang once it hits waitpid the second time, and I will never get a message saying it reaped the second child. If I spawn four child processes, then maybe two will get reaped, then it will hang. What is going on here? Do I have to do some sort of blocking of the SIGCHLD signal? If so, where should I be blocking it?
I wrote the following program to understand the way fork works when called without wait() or waitpid().
int main()
{
pid_t childpid;
int retval = 0;
int i;
while(1){
//usleep(1);
childpid = fork();
if (childpid >= 0)
{
i++;
if (childpid == 0)
{
exit(retval);
}
else
{
//printf("childpid is %d\n", childpid);
}
}
else
{
printf("total no. of processes created = %d\n", i);
perror("fork");
exit(0);
}
}
}
Here's the output I get->
total no. of processes created = 64901
fork: Cannot allocate memory
I expected the program to go on as I'm exiting the child process instantly and fork() should reuse the pids after pid > pid_max. Why doesn't this happen?
The exited child processes do remain in the process table as zombies. Zombie processes exist until their parent calls wait or waitpid to obtain their exit status. Also, the corresponding process id is kept, to prevent other newly created processes of duplicating it.
In your case, the process table becomes too large and the system rejects the creation of new processes.
Forking processes and then not retrieving their exit status can be regarded as a resource leak. When the parent exits, they will be adopted by the init process and then reaped, but if the parent stays alive for too long, there is no way for the system to just remove some of the zombies, because it is assumed that the parent should get interested in them at some point via wait or waitpid.
Child processes also hold some resource like memory. But they are not released because parent process can not process SIGCHLD signal, which will be sent by child processes when they exit.
Those child processes will become zombie.
You can use "ps -aux" to dump those fd.
how to print the current process state
main ()
{
pid_t pid;
printf("parent : %d\n", getpid());
pid = fork();
if (pid == 0)
{
printf("child : %d\n", getpid());
sleep(2);
printf("child exit\n");
exit(1);
}
while (1)
{ /*after the child exit, its a zombie process */
system("clear");
system("ps -x | grep t"); /* if a.out is Z means zombie process */
sleep(8);
}
}
Is there any other method or way to view the current process state in output
itself..?
Determining the scheduling state of a process is OS specific. On Linux, top and similar read it from the third field in /proc/$PID/stat.
You can always open and read /proc files in C
/proc/[pid]/stat and /proc/[pid]/status would give the status of the current proces.
The third field in /proc/<pid>/stat contains the process status: R if it's Running, S if it's Sleeping (there's a few others too, like D for Disk Wait and Z for Zombie).
Or you can parse the output of ps command using popen. But remember ps command itself is implemented based on the information from /proc filesystem
I was given this starter code for a project, but am having difficulty understanding how the child process executes.
int pid ;
int child_info = -1;
if ( argv[0] == NULL ) /* nothing succeeds */
return 0;
if( (pid= fork()==-1)
perror("fork");
else if ( pid == 0 ){
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
execvp(argv[0], argv);
perror("cannot execute command");
exit(1);
}
else { //check if wait error or print out exit status
if ( wait(&child_info) == -1 )
perror("wait");
else {
printf("Exit status: %d, %d\n", child_info>>8, child_info&0377);
}
}
return child_info;
}
Looking at the code, the current process forks and in this case, the child inherits all of the relevant properties of the parent process, since there are no timers, signals or anything involved. However, the pid values of the new processes are in the 18000 range, so how can execvp(argv[0], argv) be executed since in this case, pid != 0.
From the fine manual for fork:
Upon successful completion, fork() shall return 0 to the child process and shall return the process ID of the child process to the parent process.
The first branch of the if is an error condition and will be executed in the parent process if there was an error. The second branch (pid == 0) is executed in the child process, the child does a bit of signal housekeeping and does the exec. The third branch is in the parent when there was no error.
In the parent, pid will be non-zero but in the new child process, pid will be zero.
It gets executed in the child process, where pid will be 0.
http://linux.die.net/man/2/fork
Fork returns the pid of the child to the parent process and 0 to the child process. so when asking for pid == 0 means "is this the child process?". If so, it executes the program passed through command line arguments.
There's only one new process created; the child.
fork() in the child process returns 0, which is what you're checking for.
fork() in the parent process (your original process) returns the child process' pid.
By checking the return of fork() for 0 you know if you're the parent or child; you're the child if it's 0.
On success, the PID of the child
process is returned in the parent’s
thread of execution, and a 0 is
returned in the child’s thread of execution.
p = fork();
I'm confused at its manual page,is p equal to 0 or PID?
I'm not sure how the manual can be any clearer! fork() creates a new process, so you now have two identical processes. To distinguish between them, the return value of fork() differs. In the original process, you get the PID of the child process. In the child process, you get 0.
So a canonical use is as follows:
p = fork();
if (0 == p)
{
// We're the child process
}
else if (p > 0)
{
// We're the parent process
}
else
{
// We're the parent process, but child couldn't be created
}
p = fork();
/* assume no errors */
/* you now have two */
/* programs running */
--------------------
if (p > 0) { | if (p == 0) {
printf("parent\n"); | printf("child\n");
... | ...
Processes are structured in a directed tree where you only know your single-parent (getppid()). In short, fork() returns -1 on error like many other system functions, non-zero value is useful for initiator of the fork call (the parent) to know its new-child pid.
Nothing is as good as example:
/* fork/getpid test */
#include <sys/types.h>
#include <unistd.h> /* fork(), getpid() */
#include <stdio.h>
int main(int argc, char* argv[])
{
int pid;
printf("Entry point: my pid is %d, parent pid is %d\n",
getpid(), getppid());
pid = fork();
if (pid == 0) {
printf("Child: my pid is %d, parent pid is %d\n",
getpid(), getppid());
}
else if (pid > 0) {
printf("Parent: my pid is %d, parent pid is %d, my child pid is %d\n",
getpid(), getppid(), pid);
}
else {
printf("Parent: oops! can not create a child (my pid is %d)\n",
getpid());
}
return 0;
}
And the result (bash is pid 2249, in this case):
Entry point: my pid is 16051, parent pid is 2249
Parent: my pid is 16051, parent pid is 2249, my child pid is 16052
Child: my pid is 16052, parent pid is 16051
If you need to share some resources (files, parent pid, etc.) between parent and child, look at clone() (for GNU C library, and maybe others)
Once fork is executed, you have two processes. The call returns different values to each process.
If you do something like this
int f;
f = fork();
if (f == 0) {
printf("I am the child\n");
} else {
printf("I am the parent and the childs pid is %d\n",f);
}
You will see both the messages printed. They're being printed by two separate processes. This is they way you can differentiate between the two processes created.
This is the cool part. It's equal to BOTH.
Well, not really. But once fork returns, you now have two copies of your program running! Two processes. You can sort of think of them as alternate universes. In one, the return value is 0. In the other, it's the ID of the new process!
Usually you will have something like this:
p = fork();
if (p == 0){
printf("I am a child process!\n");
//Do child things
}
else {
printf("I am the parent process! Child is number %d\n", p);
//Do parenty things
}
In this case, both strings will get printed, but by different processes!
fork() is invoked in the parent process. Then a child process is spawned. By the time the child process spawns, fork() has finished its execution.
At this point, fork() is ready to return, but it returns a different value depending on whether it's in the parent or child. In the child process, it returns 0, and in the parent process/thread, it returns the child's process ID.
Fork creates a duplicate process and a new process context. When it returns a 0 value it means that a child process is running, but when it returns another value that means a parent process is running. We usually use wait statement so that a child process completes and parent process starts executing.
I think that it works like this:
when pid = fork(), the code should be executed two times, one is in current process, one is in child process.
So it explains why if/else both execute.
And the order is, first current process, and then execute the child.