C : Store PID in global variable - c

I am currently working on a school project and I wanted to store the PID of my process in the global array id, so that I can use it in another function :
int id[3];
int main(int agrc,const char* agrv[]) {
for(int i = 0; i < 3; i++) {
if((fork() == 0)) {
id[i] = (int)getpid();
printf("ID[%d] = %d\n",i,id[i]);
if(i != 3) {
printf("I am a wharehouse. PID = [%d] PPID = [%d]\n",getpid(),getppid());
whcode();
exit(0);
}
else if(i == 3) {
printf("I am the central. PID = [%d] PPID = [%d]\n",getpid(),getppid());
central_code();
exit(0);
}
}
}
sleep(2);
printf("ID[0] = %d\n",id[0]);
printf("ID[1] = %d\n",id[1]);
printf("ID[2] = %d\n",id[2]);
}
But when I run this the output of the last 3 prints is 0, where it should be the PID of each process. Why does this happen?

On the call to fork(), new process is created with separate virtual memory space. This child process will return from the call to fork with 0, so in your code, this child will go inside the if branch and assign to id[i] it's pid. But this assignment is happening in a separate process, with separate virtual memory, so it has no effect on the parents virtual memory space and the parent will not see any change in its array. That is why your code prints the zeroes.
If you want to print the pids of the children by the parent, use the return value of fork(), which in parent is the pid of the child process. Inside the for, use code such as this:
pid_t child_id;
switch (child_id = fork()) {
case -1:
//Fork failed, exit with error or something
break;
case 0:
//Child code
printf("ID[%d] = %d\n",i,id[i]);
if(i != 3) {
printf("I am a wharehouse. PID = [%d] PPID = [%d]\n",getpid(),getppid());
whcode();
exit(0);
}
else if(i == 3) {
printf("I am the central. PID = [%d] PPID = [%d]\n",getpid(),getppid());
central_code();
exit(0);
}
break;
default:
id[i] = child_id;
break;
}
By the way, you should really declare the id array as pid_t id[3], and when printing, print it as long. That for now is probably the most portable way to handle these things.

Related

Not fully understanding fork for switch program output

I have been trying to understand the output of this program, but still I don’t quite get it.
main()
{
int pid, i;
pid = getpid();
for (i = 0; i < 25; i++)
{
switch (fork())
{
case 0:
if (pid % 2 == 0)
{
exit(0);
break;
}
default:
if (pid % 2 != 0)
{
exit(0);
}
}
}
printf("I am the process %d and my father is the process %d\n", getpid(), getppid());
while (wait(NULL) > 0) {}
return 0;
}
When I run this, it returns:
I am the process 11110 and my father is the process 26453
However, if you were to run the above code without both "% 2", it won't return anything.
I am very confused about this. The way I thought it would work (for the code without "% 2") is, for each for iteration:
the child (pid==0) would finish its process (killing the child process) and always break from the switch (not affecting the for loop)
the father/main process will wait until the child dies
next for iteration
Is the above approach correct? If so, how would it be with "% 2"?
Without % 2 you'd get:
switch (fork())
{
case 0:
if (pid == 0)
{
exit(0);
break;
}
default:
if (pid != 0)
{
exit(0);
}
}
Since pid is not 0, the parent would exit(0) immediately after the first fork(), so you won't see a print statement.

Trying to store the PID's of every child process

I am currently learning about the fork() function in c. I was playing around with the child pid's and trying to store them within an array but keep coming across errors:
void store(int pid){
int arr[10];
int i = 0;
for(i = 0; i < 10; i++){
if(arr[i] == 0){
arr[i] = pid;
printArray(arr);
break;
}
}
}
int stuff(int a){
int status = fork();
if(status == 0){
printf("PID IS %d\n", getpid());
store(getpid());
}
else {
printf("PID IS %d\n", getpid());
store(getpid());
}
return a + 1;
}
int main(int argc, char * argv[]){
int a = stuff(10);
return 0;
}
Instead, this outputs the same array with the two different PIDS in the same array index. I am not too sure what exactly is happening here and would be grateful for any explanation.
Keep it in mind that fork function is called once but returns twice. The difference in the returns is that the return value in the child
is 0, whereas the return value in the parent is the process ID of the new child. The child process and the parent process run in separate memory spaces.
That's the reason why your program outputs the same array with the two different PIDS in the same array index.
int stuff(int a){
int status = fork();
// fork will return a value of pid_t type
pid_t status = fork();
if(status == 0){
// this is in the child process, so getpid() will return the pid of the child
printf("PID IS %d\n", getpid());
store(getpid());
}
else {
// this is in then parent process, so getpid() will return the pid of the parent
printf("PID IS %d\n", getpid());
store(getpid());
}
return a + 1;
}

How to create chain of processes in C?

I need to create 5 processes one being father of the second, grandpa of the third etc. All of them have to wait for each other to finish. I tried the approach with:
switch (pid = fork()) {
case 0:
printf("Child PID = %d\n", getpid());
printf("parent: =\%d\n", getppid());
return 0;
default:
break;
But I always get the same parent.
You need to use recursion.
For example:
void create_processes(int n) {
if(n == 0) return;
if(fork() == 0) {
int status;
// You're in the child process. Calling it recursively will have the
// child's PID as parent
create_processes(n - 1);
// Do work you need done before the child terminates
wait(&status);
// Do work you need done after the child terminates
}
}
Then call it like
create_processes(5);
Call a process myProcess that returns no type and takes an int as a parameter. Then...
void myProcess(int x)
{
if (x > 5) return;
if (x != 0)
myProcess(x - 1);
return;
};
int main()
{
int myvar = 5;
myProcess(myvar);
return 0;
}
It's done recursively.

Multiple Child Processes from one Parent Process

I'm implementing a simple parent/child process program using fork. My goal is to create a user input number of child processes from a single parent and store their PIDs in a dynamic array. I manage to create the child processes (I think) using fork and store their PIDS. However, when I store the PIDs, I also store the 0 PID and what I believe another PID related to the processes yet this number is quite bigger than the child and parent.
How come this happens when clearly this is only done inside the parent process?
void createProcesses(int nProcess) {
int i;
int PID;
processIDS = calloc(nProcess, sizeof(long));
printf("*****Creating Processes*****\n");
printf("Parent Process: PID %d\n", getpid());
for (i = 0; i < nProcess; i++) {
PID = fork();
if (PID == 0) {
printf("Child Process: PID %d\n", getpid());
while(1){}
}
else if(PID != 0) {
// sleep(3);
// printf("Number of child processes created: %d\n", nProcess);
// updateProcessList();
*(processIDS + i) = PID;
printf("%d\n", PID);
}
}
for(i = 0; i < sizeof(processIDS); i++) {
printf("%ld\n", *(processIDS + i));
}
while(1) {
sleep(5);
updateProcessList();
}
}
processIDS is a long * global variable.
The problem is here:
for(i = 0; i < sizeof(processIDS); i++) {
printf("%ld\n", *(processIDS + i));
}
Because processIDS is a pointer, it's size is the size of a long *, probably 4 or 8, which is not what you want. If the value of nProcess is less than this, you'll be reading off the end of the dynamically allocated array, invoking undefined behavior.
You know there are nProcess processes created, so use that for your loop test:
for(i = 0; i < nProcess; i++) {
printf("%ld\n", *(processIDS + i));
}

Semaphores, processes and incrementing variables in shared memory

This is a homework question. I have to write a program forking itself 20 times. Each new process is adding +1 to a variable (integer) which is shared between all of them. The thing is, I have to use semaphores (IPC). This piece of code is 'working' - giving the value of 20 in the end.
*buf = 0;
for(i=1; i<=20; ++i)
{
if(fork()!=0)
{
*buf += 1;
exit(0);
}
}
EDIT:
Based on this code I am trying to get output like :
I am child 1...
I am child 2...
.
.
.
I am child 20...
It worked once (first time), and then the order became random. But I did not change any code. What am I doing wrong?
Well your major problem is this:
if (fork()!=0) //<-- this
fork() will return -1 on error, the parent pid, OR ZERO for the child. So you are actually doing everything in the parent. Change to (fork() ==0) and it does what you want.
Also you should wait on your children and detach shared memory. (I added some output of the process ids to make it a little clearer.)
printf("I AM THE PARENT pid = %d\n", getpid());
*buf = 0;
for(i=1; i<=20; ++i)
{
if((pid = fork()) == -1)
{
perror("fork");
exit(1);
}
if (pid == 0)
{
v(semid, 0);
*buf += 1;
p(semid, 0);
printf("I am child %d with pid = %d\n", i, getpid());
shmdt(buf);
exit(0);
}
}
for (i = 1; i <= 20; ++i)
{
pid = wait(&status);
printf("child pid = %d reaped\n", pid);
}
printf("buf: %p\n", buf);
printf("*buf: %d\n", *buf);
shmdt(buf);
return 0;

Resources