Multiple Child Processes from one Parent Process - c

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));
}

Related

C creating processes with Fork()

int main()
{
int i;
int status;
for (i = 0; i < 4; i++) {
if(fork() == 0){
sleep(1);
}
}
printf("This is the end.\n");
return 0;
}
I need to change the code so that exactly 4 child processes will be created. I have tried a few things but Im not sure how to do it.
You have to prevent the child processes from creating new child processes. To do so, just exit the loop in a child process.
for (i = 0; i < 4; i++) {
if(fork() == 0) {
// Only the child process will execute this
sleep(1);
break;
}
}

C : Store PID in global variable

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.

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 processes work sequentially with C pipe?

I want to do that 2 child processes will put their names and wait until other process put his name. For instance, if there are first and second process, first will put her name and will wait for other's name in screen. So I want to work with processes and I wanna to see they are working sequentially.
Output:
first
second
first
second
first
second
I just tried something about C(linux).
int main(void)
{
pid_t child_a, child_b;
int pipe1[2], pipe2[2];
char mesazhi1[] = "first";
char mesazhi2[] = "second";
char buf[1024];
int first_pipe = pipe(pipe1);
pipe(pipe2);
if(first_pipe == -1){
perror("pipe");
exit(1);
}
child_a = fork();
if (child_a == 0)
{
/* Child A code */
int i;
for (i = 0; i < 3; i++)
{
write(pipe1[1],mesazhi1, strlen(mesazhi1) + 1);
//printf("first\n");
int a = read(pipe2[0], buf, strlen(mesazhi2) + 1);
printf("%s - %d\n", buf, a);
}
}
else
{
child_b = fork();
if (child_b == 0)
{
int i;
for (i = 0; i < 3; i++)
{
write(pipe2[1],mesazhi2, strlen(mesazhi2) + 1);
//printf("second\n");
int a = read(pipe1[0], buf, strlen(mesazhi1) + 1);
printf("%s - %d\n", buf, a);
}
}
else
{
/* Parent Code */
int returnStatusA,returnStatusB;
waitpid(child_a, &returnStatusA, 0); // Parent process waits here for child to terminate.
waitpid(child_b, &returnStatusB, 0); // Parent process waits here for child to terminate.
if (returnStatusA == 0 && returnStatusB == 0) // Verify child process terminated without error.
{
printf("%s\n", "The child processes terminated normally.\n");
}
if (returnStatusA == 1 && returnStatusB == 1)
{
printf("%s\n", "The child processes terminated with an error!. \n" );
}
}
}
}
It is putting name randomly. I mean that I think, sometimes second process works faster than first. Output like that:
first
second
second
first
second
...
So why second process doesn't wait for first one, because I think that read() function should wait until there is something in pipe1.
In the posted code, both processes write to their respective pipes, and then read. After that, it's a race to see which process gets to print first.
For a more controlled situation, have child B call read and printf before calling write. That way B has to wait for A before printing, and vice versa.
if (child_b == 0)
{
int i;
for (i = 0; i < 3; i++)
{
int a = read(pipe1[0], buf, strlen(mesazhi1) + 1);
printf("%s - %d\n", buf, a);
write(pipe2[1],mesazhi2, strlen(mesazhi2) + 1);
}
}

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