Write a C program that sets an environment variable called done to 0.
The program will then ask the user to enter 5 numbers in a loop and store the numbers in an array of 5 int elements.
The program will then creates a clone process (using fork()).
The clone should run a function called sum() that calculates the total sum of all the numbers in the array.
After that the clone will set the done environment variable to 1. It will also create a second environment variable called result and will set it to the return value of the sum()function.
The parent process wait on done variable until it is set to 1.
If it is 1, the parent will print to the screen : The sum of elements is: result.
Note that result is the content of the environment variable called result.
Please note that you need to choose a suitable signature for your sum()function,
meaning that it is up to you to decide about the type and the number of arguments as well as the type of the return value.
I am not sure why my program is not working.
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
int sum(int a[], int size) {
int index, result = 0;
for (index = 0; index < size; index++) {
result+=a[index];
return result;
}
}
int main() {
int i, array[5], result;
long pid;
char string[20];
for (i = 0; i < 5; i++) {
scanf("%d", &array[i]);
if (i == 4) {
}
}
setenv("done", "0", 1);
pid = fork();
if (pid == 0) {
result = sum(array,5);
sprintf(string, "%d", result);
setenv("result", string, 1);
setenv("done","1",1);
}
else {
while (strcmp(getenv("done"), "0") == 0) {
}
result = atoi(getenv("result"));
printf("The sum of elements is %d\n", result);
}
return 0;
}
This my not be the answer you desire, but 2 way communication via environment variable is near impossible because as pointed out in the comment a child process could not affect its parent process environment.
I would suggest you look at inter process communication :
Shared memory
Pipe
Socket
RPC
Related
The C script is supposed to take x amount of CPU bound forks and x amount of IO bound forks, so then lets say 10 total processes if you there's 5 of each. If I fork 10 times, then 5 of those should go to working on the CPU bound "fake work" and 5 of those should go to the IO bound "fake work". Waitstats is a custom function that serves the purpose of wait while also displaying rtime and wtime.
My problem is that I've tried multiple configurations and I'm not sure how to get the Process Number printf to correctly print, only 10 times, if there's only 10 forks? I also feel as if I'm not doing my fake work correctly for the CPU/IO bound work.
Any help here would be appreciated!
`
int main(int argc, char* argv[])
{
int cpuNum = atoi(argv[2]);
int ioNum = atoi(argv[4]);
int const MAX_PROC = cpuNum + ioNum;
printf("\nMax Proc %d", MAX_PROC);
int totRunTime = 0;
int totWaitTime = 0;
uint rTime = 0;
uint wTime = 0;
int pid = 0;
//Create Max_Proc Forks
for(int n=0; n < MAX_PROC; n++)
{
pid = fork();
//If Child, Exceute Command
if(pid == 0)
{
break;
}
}
if (cpuNum > 0) {
//CPU Busy Work
for (volatile int i = 0; i < 1000000000; i++){}
cpuNum--;
}
else if (ioNum > 0) {
//IO Busy Work
sleep(200);
ioNum--;
}
for(int p=0; p < MAX_PROC; p++)
{
printf("\n Process %d finished", p);
if(waitStats(0, &rTime, &wTime) >= 0)
{
totRunTime += rTime;
totWaitTime += wTime;
}
}
printf("\nAverage rtime %d, wtime %d", rTime, wTime);
exit(0);
}
`
I've tried multiple configurations, but can't seem to get the printf to print the correct process/fork number. For instance forking 10 times would mean I would need to printf every time one of those forks finished their task (10 total times).
The code shown doesn't print pids, so I'm assuming you mean "process number" as in 1st child, 2nd child etc.
Every one of your processes is running this:
for(int p=0; p < MAX_PROC; p++)
{
printf("\n Process %d finished", p);
...
So it looks like each process will print the numbers 0 .. MAX_PROC-1 (with no indication of which pid is printing)
Have you tried putting the waitStats for loop inside of your "Create Max_Proc Forks" for loop? So then basically everything should be inside of the first loop, probably giving you a good way to keep track of the process number?
I have a school project which requires me to simulate first come first serve using these variables:
Users Input:
Number of Process: 3
Process 1 Arrives at 0 time and requires 5 'resources'
3
1,5,0
2,5,4
3,1,8
However, i can't seem to get past the first 5 'resources'. I'm trying to figure out how to increase PID and repeat but keep time increasing for all these resources. I've created this same program but it only allows for this specific input and I'm trying to make it more versatile so i can choose any number of processes and resources(unit) needed.
#include <stdio.h>
main() {
int n;
printf("Enter the Amount of processes: ");
scanf("%d",&n);
//Variables
int process[n], unit[n], at[n];
int i,time,PID = 1;
int awt, atat,sum,counter;
int x = n;
//Takes and stores the users input into process unit and at
for(i=0;i<n;i++)
{
scanf("%d,%d,%d", &process[i], &unit[i], &at[i]);
}
sum = sum_array(unit,n);
printf("%d\n", sum);
printf("FCFS\n");
printf("Time PID");
for(counter = 0; counter < x; counter++, PID++){
FCFS(time,n,unit,PID);
}
}
int sum_array(int at[], int num_elements){
int x, sum = 0;
for(x=0; x<num_elements;x++){
sum = sum + at[x];
}
return(sum);
}
int FCFS(int time,int n,int unit[], int PID){
for(time = 0, n = 0 ; unit[n] >0 ;time++, unit[n]--){
printf("\n%d ", time);
printf("%d", PID);
}
return;
}
Sample Output:
FCFS
TIME PID
0 1
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 2
9 2
10 3
Your problems are mostly related to the FCFS function and the loop where you call it.
Try the following:
Initialize time = 0 in the main function
Pass counter instead of n to FCFS in the loop
Return the updated time from FCFS
Don't reset the time and n parameter inside FCFS
Call to FCFS inside for loop:
time = FCFS(time, counter, unit, PID);
Updated FCFS code:
int FCFS(int time,int n,int unit[], int PID)
{
for( ; unit[n] >0 ;time++, unit[n]--)
{
printf("\n%d ", time);
printf("%d", PID);
}
return time;
}
Other than that, there are a number of issues with your code, but it wouldn't really fit into this Q/A to mention them all, so I stick with the necessary things to get your code running for valid example input.
Since this is a homework question, I would encourage you to solve it on your own. Since you have put in some effort on solving this, I am posting the answer below as a spoiler (Note indentation does not work in spoilers). However before seeing the answer here are few suggestions to fix your program:
As mentioned above, passing n does absolutely nothing. Please use a different variable inside the FCFS function.
No need to increment and pass the PID. Since you are putting it in an array, try to get the value from the array.
Instead of n pass counter to the function so that you can index the two arrays.
The for loop inside FCFS makes no sense. It should be for(i=0; i<unit[counter]; i++). time can just be incremented inside the loop.
time needs to be returned to increment properly
And my code:
int time = 0;
int cur_index = 0;
while (cur_index < n) {
int pid = -1;
if (at[cur_index] <= time) {
pid = process[cur_index];
} else {
printf("%d %d\n", time, pid);
time++;
continue;
}
if (pid != -1) {
int r = 0;
for (r = 0; r < unit[cur_index]; r++) {
printf("%d %d\n", time, pid);
time++;
}
}
}
I have to find the biggest value in an array of a 1000 numbers with 10 child processes (so that every one of them only checks a hundred values), and the parent only has to collect the data.
I'm already done with the whole thing, but I'm stuck at reading the values.
Here's the code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(){
int array[1000];
int i, j;
int pids[10];
int searchminindex;
int searchmaxindex;
int maxindex;
srand(time(NULL));
//fill up array with random numbers
for(i = 0; i < 1000; i++)
{
tomb[i] = random() % 5000;
}
//create 10 child processes
for (i = 0; i < 10; i++) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
}
else if (pids[i] == 0) {
searchminindex = i * 100;
searchmaxindex = (i+1) * 100;
//finding the biggest value
maxindex = searchminindex;
for(j = searchminindex+1; j < maxindex; j++) {
if( array[maxindex] < array[j])
maxindex = j;
}
}
}
for(i = 0; i < 10; i++){
//here's where I'd read the return values of the subarrays
}
return 0;
}
I've tried using pipes and also using WEXITSTATUS, but I'm really confused and don't know where to close one end of the pipe and things like that, and with WEXITSTATUS I'm completely lost.
Any way you could help?
You need to test the pid returned from fork, and branch your code so your main process doesn't act like a child, and so that your children don't spawn children of their own. Once that's taken care of...
An alternative to mmap or setting up shared memory at all is to use WEXITSTATUS. According to the man page, it'll only return the least significant 8 bits, so if your return values can be greater than 127, this is likely not your best option. Can be made to work up to 255, but be careful about signedness of char, it's not standard.
int returned_values[10];
for(int i = 0; i < 10; ++i)
{
int status;
wait(&status);
if(WIFEXITED(status))
returned_values[i] = WEXITSTATUS(status);
else {
//Do something more meaningful here
//This means a child received a signal, or any of the other ways wait returns other than a child exiting.
--i;
}
You need to test the pid returned from fork, and branch your code so your main process doesn't act like a child, and so that your children don't spawn children of their own. Once that's taken care of...
Sharing memory between forked processes is explained well here
I would use mmap to create shared memory between the processes, you'll need to specify for each process where to put it's result, then use wait to determine when all children have exited, and a good program would evaluate the exit status and inform the user if any child exited abnormally.
Don't forget to clean up the shared memory before the parent exits.
Currently working on some homework and having a hard time. The goal is to generate 100,000 numbers and add them all together by dividing the work into 10 processes (10,000 numbers each)
I think I've figured out how to fork processes (hopefully), but using Pipe() to relay the subtotals from each child process is not working... the program below returns 44901 for each child process and 449010 for the running total.
I'm struggling hard but I feel like this is something simple I should be able to understand.
main()
{
int i;
pid_t pid;
int status = 0;
int fd[2];
int runningTotal = 0;
pipe(fd);
int t;
int r;
for (i = 0; i < 10; i++) {
pid = fork();
if (pid == 0){
close(fd[0]);
t = ChildProcess();
write(fd[1], &t, sizeof(t));
exit(0);
}
close(fd[1]);
read(fd[0], &r, sizeof(r));
runningTotal = runningTotal + r;
wait(&status);
}
printf("%i\n", runningTotal);
}
int ChildProcess() {
int i;
int total = 0;
int r = 0;
for (i = 0; i < 10000; i++) {
r = rand() % 10; // 0 to 10
total = total + r;
}
printf("%i\n", total);
return total;
}
Ordinarily, one would use a separate pipe for each child, for otherwise it's impossible for the parent to know from which process the data it reads comes. I don't think that's so much of an issue in this particular case, though, because here, you actually don't care. Although it still makes me cringe a bit, I think you indeed can get away with just one pipe for this particular task.
In fact, I don't think your problem is with the pipe at all. It is with rand(). All child processes compute exactly the same sequence of (pseudo-)random numbers because they all use the same (default) seed. If you want to produce different sequences of numbers, then you need to call srand() in each child process, giving a different seed in each one. The sequence of numbers rand() will generate is completely determined by the seed with which it starts.
Note, too, that if the system's random number generator is any good at all, then all the sums computed by the various processes should be very close to each other, and to the result you reported. This is a consequence of the Central Limit Theorem in statistics, but you can think of it simply as the larger results balancing the smaller ones on average. There's probably a slight bias arising from calculating the remainder mod 10.
Initial diagnosis
If your concern is that the children are all producing the same values, then the problem is that they're all using the same random sequence because you don't call srand() anywhere. You need to call it once per child, with a different seed for each child.
It isn't 100% reliable, but you could probably get away with srand(time(0) + getpid()); in each child — or even just getpid() since those values are guaranteed to be different.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int ChildProcess(void)
{
int total = 0;
srand(time(0) + getpid());
for (int i = 0; i < 10000; i++)
{
int r = rand() % 10; // 0 to 9 (not 10).
total = total + r;
}
printf("%i\n", total);
return total;
}
Further scrutiny
Actually, on closer examination, there's another problem. The parent process closes the write end of the pipe after forking the first child, so the subsequent children don't have a usable file descriptor to use. The read value will always be the one from the first child. So, you need to do more serious work.
int main(void)
{
int fd[2];
pipe(fd); // Missing error check
for (int i = 0; i < 10; i++) {
pid_t pid = fork();
if (pid == 0){
close(fd[0]);
int t = ChildProcess();
write(fd[1], &t, sizeof(t)); // Missing error check?
exit(0);
}
// Print PID here? Error check?
}
close(fd[1]);
int r;
int runningTotal = 0;
while (read(fd[0], &r, sizeof(r)) > 0) // Debugging opportunities here
runningTotal = runningTotal + r;
while (wait(0) > 0) // Lots of debugging opportunities here
;
printf("%i\n", runningTotal);
return 0;
}
given this code: (an excerpt from the posted code)
for (i = 0; i < 10; i++) {
pid = fork();
if (pid == 0){
close(fd[0]);
t = ChildProcess();
write(fd[1], &t, sizeof(t));
exit(0);
}
close(fd[1]);
read(fd[0], &r, sizeof(r));
runningTotal = runningTotal + r;
wait(&status);
}
there is a sequence problem.
When the parent closes the fd[1] during the first iteration of the loop, that file descriptor does not 'magically' open again for the next iteration of the loop.
The code for the parent, in the loop, needs to check the returned value from the call to read() to assure the operation was successful. (it probably was not successful after the first iteration through the loop, so the variable 'r' will be unchanged.
I'm writting a program that needs to pass a matrix from a parent process to its child (that's why I'm using the fork() instruction). I've just read this and this to solve the problem myself, but I still can't understand how to use the read() and write() instructions with the pipe I've created so far. I know these instructions write series of bytes, but I'm not sure about using them with structures or dynamically allocated variables (like a matrix).
Here is the code I used to test (note the comments I put):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
// Structure definition (Matrix)
typedef struct {
int **mat;
int rows;
int cols;
} Matrix;
int main() {
// Create the pipe
int file_desc[2];
if (pipe(file_desc) != 0) exit(1);
// Create two processes
if (fork() == 0) {
/** Instructions for the child process */
// Read the matrix structure from the pipe
Matrix *received = NULL;
read(file_desc[0], received, sizeof *received);
if (received != NULL) {
// Print the received matrix
int i, j;
printf("The matrix I've just *received* from the parent is:\n");
for (i = 0; i < received->cols; i++) {
for (j = 0; j < received->rows; j++) printf("%d\t", received->mat[i][j]);
printf("\n");
}
} else printf("received = NULL :'(\n");
} else {
/** Instructions for the parent process */
/* Create a matrix dinamically.
* In fact, in the real program I have a function to create a matrix given the
* rows and columns, and fill it with random values, so it returns a Matrix *
* (pointer to Matrix), but for testing purposes I've only written this
* (also useful if I need an array of Matrix elements, for example)
* */
Matrix *myMatrix = calloc(1, sizeof *myMatrix);
// Put the contents into the variable
myMatrix->rows = 2;
myMatrix->cols = 2;
myMatrix->mat = calloc(myMatrix->rows, sizeof *(myMatrix->mat));
int i, j;
for (i = 0; i < myMatrix->cols; i++)
(myMatrix->mat)[i] = calloc(myMatrix->cols, sizeof **(myMatrix->mat));
// Fill the matrix with some values (testing)
(myMatrix->mat)[0][0] = 4;
(myMatrix->mat)[0][1] = 2;
(myMatrix->mat)[1][0] = 1;
(myMatrix->mat)[1][1] = 3;
// Print the matrix
printf("The matrix I've just filled in the parent is:\n");
for (i = 0; i < myMatrix->cols; i++) {
for (j = 0; j < myMatrix->rows; j++) printf("%d\t", myMatrix->mat[i][j]);
printf("\n");
}
// Write the matrix structure to the pipe (here is where I have the problem!)
write(file_desc[1], myMatrix, sizeof *myMatrix);
// Wait for the child process to terminate
wait(0);
printf("The child process has just finished, the parent process continues.\n");
}
return 0;
}
In fact, I tried first with a pointer to an int and it worked. But when I run this program, I receive this output:
The matrix I've just filled in the parent is:
4 2
1 3
received = NULL :'(
The child process has just finished, the parent process continues.
And I don't know why I get the NULL -- I'm almost sure I'm using the write() instruction incorrectly. Any help about this will be appreciated =)
EDIT: I think the matrix should be converted to text, for example, and then pass the string to the child, parse it and convert it to a Matrix structure again. I don't know if this approach is the best. Is there another approach besides this one?
EDIT: I tried the same code with a static variable (changing int **mat; to int mat[2][2]; inside the structure declaration) but the user should change the matrix size.
This is a serious problem:
Matrix *received = NULL;
read(file_desc[0], received, sizeof *received);
Received is a null pointer. That read is going to try to write data to NULL, which is an invalid address. It would be much simpler to write:
Matrix received;
read(file_desc[0], &received, sizeof received);