So I'm forking a couple of child processes and each of them is supposed to take a line that I've read from a file and do operations on them.
What I have is a struct containing the lines like :
struct query {
char lines[LINESIZE];
};
and I have an array of structs. So each struct serves to one child process.
This is how I forked my child processes :
for(i=0; i<5; i++) {
n = fork();
}
And say I have five structs to serve for each of these processes.
struct query query[5];
So First processes takes query[0].lines and do some operations on it, second process gets query[1].lines and does the same operations on it and so on ...
Should I use pipe to pass values between processes? I feel like there's a much simpler solution to this but my lack of practice and knowledge in C is really slowing me down.
I suppose you're trying to spawn 5 processes, but in the code that you posted you'll end up creating way more than 5 processes, in fact in:
for(i = 0; i < 5; ++i) {
n = fork();
}
when i = 0 you'll fork a process, since the forked process is an exact copy of the parent it will continue in the for loop, so at that point you'll have two processes each one having i = 1 and forking each one a new process, then you'll have at this point 4 processes, when the loop is complete you have created 160 processes.
Allocating and initializing the array "query" before the forking it is perfectly fine what you have to fix is the spawning. The fork() call returns 0 in the child process, the process id of the child to the parent process or -1 if there was a error. Knowing if the current process is the parent or the child we can continue or break out of the loop and do the computation:
for(i = 0; i < 5; ++i) {
if(fork() == 0) {
/* child process */
process_query(query[i]);
exit();
}
}
Related
I want to know the number of processes created for the below code. I got to know from my instructor the answer is 41 but I am unable to follow the same. Please explain the same with a process tree.
void main() {
for (i=0;i<2;i++){
fork();
if(!fork()) {
execl("/bin/ls","ls",NULL);
fork();
}
fork();
}
fork();
}
This looks like a homework question. If we would draw a process tree for you, you might get some points now, but you will not learn how to analyze a program, and this may hurt you later. You will learn more by understanding how the program works. (Of course, this program is an academic example and not very useful except for learning.)
I suggest to mark the fork calls with letters.
int main(void) {
for (int i = 0; i < 2; i++) {
fork(); /* A */
if(!fork()) { /* B */
execl("/bin/ls","ls",NULL);
fork(); /* C */
}
fork(); /* D */
}
fork(); /* E */
}
Take paper and pencil, write down what happens and draw a tree using the loop counter and the marked fork calls.
Example:
The program runs a loop for two cycles (0 and 1), the loop continues in all processes.
In parent P, loop cycle 0, fork A will create child 1.
P -(0,A)-> 1
Still in loop cycle 0, both P and 1 will run the fork B inside the condition, creating a new child each.
P -(0,B)-> 2, 1 -(0,B)-> 3.
Think about the meaning of the condition and decide which processes run the conditional block.
Think about what happens after execl, e.g. process x executes ls, resulting in ...
Some processes (name them) will reach D and create a child each, all will continue with loop cycle 1...
etc.
To see what happens you could add some output after every fork to display what happens: which loop index, which fork, is the process parent or child of this fork, PID, parent PID. And before the execl display which PID is about to call it. (Note that buffered output like printf may show unexpected behavior in combination with fork, so it might be better to use sprintf and write.) Running the program will produce output that could help you to draw a process tree. It is even possible to format the output in a way that a tree could be generated automatically using graphviz or PlantUML. All these are advanced topics.
I write a code that some processes use an array, sort it and then print it. In fact What I would like to do is that each process should sort a line of integer numbers that main process gives to them and print them, then send them back to the main process. The algorithm works fine without process and forking. But when I add forking, some process cause printing or performing some instruction more than one time or more. Please let me know how to manage it.
Here is the code:
if (N<=NumberOfLines)
{
PortionOfProcess=NumberOfLines/N;
for (int i=0;i<N;i++)//making N process using fork
{
for (int j=0; j<PortionOfProcess; j++)//For using from function by a single process
{
int pointer=i*PortionOfProcess+j;//this points to the line for each process
printf("poniter: %d . the i is %d, the j is: %d and the portionprocess is : %d\n",pointer,i,j,PortionOfProcess);
fileopener(B_result,pointer);
mypid=fork();
if (mypid==0)//child
{
///////////do the sorting
for (int j=0 ; j<(y-1) ; j++)
{
for (int i=0 ; i<(y-1) ; i++)
{
if (B_result[i+1] < B_result[i])
{
t = B_result[i];
B_result[i] = B_result[i + 1];
B_result[i + 1] = t;
}
}
}
for (int j=0 ; j<y ; j++)
{
printf("SORTED %d \n",B_result[j]);
}
//////////////////end sorting
}
}
}
}
I am new in C programming. I write a code that some processes use an array, sort it and then print it. The algorithm works fine with out process and forking
Here is what fork() does: it creates an entire new copy of the process that, in most ways, is completely independent of the original. However, the original parent process does not wait for the children to finish. Nor has it any way of communicating with the children.
What you want to do is actually quite complex. The parent and child processes needs to create some sort of communications channel. This is most usually done by creating a pipe between them. The child will then write to the pipe like a normal file and the parent will read from the pipe. The logic will look something like this:
create pipe
fork
if parent close write end of the pipe
if child close read end of pipe
The children then do their stuff and exit normally. The parent, however, has a load of files to read and it doesn't know which order to read them in. In your case the children are fairly simple, so you could probably just read each one in the order you create it, but you may also want to look at select so that you read the results in the order they are ready.
Finally, you need to call wait or waitpid so that you get the return status of each child and you do not end up with zombie processes which is a possibility because with the parent blocking on input from various pipes, any mistake you make could lead to it waiting forever (or until killed).
I'm trying to do a program with shared memory between a child process and a father process. The program also use forks.
The objetive of the exercise is:
-Father send to the child (with shared memory) 3 times a vector with active wait
-Child receive the vec, print it and change the synchronize variable
Struct:
typedef struct{
int change[NUM_TOTAL];
int synchronize;
}Exchange;
Exchange *vec;
int fd = shm_open("/shmtest8",O_CREAT| O_RDWR,S_IRUSR|S_IWUSR);
//Check shm_open error
ftruncate(fd, 100);
vec = (Exchange*) mmap(NULL,100,PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
x = forkFunc() //Creates a fork, and return 0 to parente and > 0 to child process
if(x == 0){ //Parent
int cont = 0;
while(cont != 3){
printf("Father\n");
vec->synchronize = 1; //Now go to to the child
while(vec->synchronize!=0); //the child change the variable to 0
cont++;
printf("cont %d",cont);
}
wait(NULL);
munmap(vec,sizeof(vec));
close(fd);
shm_unlink("/shmtest8");
}else if(x > 0){ //Child
int cont = 0;
while(vec->synchronize!=1); //Exit while when father change the variable to 1
int i;
for(i = 0; i < 10; i++){
printf("%d\t",i);
}
vec->synchronize =0; //Return to the father
}
Here is the exemple of an output:
Father
Child
0 1 2 3 4 5 6 7 8 9
cont 1
Father
After the first iteration the program freezes after the "while(vec->synchronize!=0);" ... i guess the problema exist in the child process, but i dont know why...Any ideas?
Thank you
I think your child process part should have 1 more while loop
while(cont != 3){
while(vec->synchronize!=1); //Exit while when father change the variable to 1
int i;
for(i = 0; i < 10; i++){
printf("%d\t",i);
}
ec->synchronize =0; //Return to the father
cont++
}
Don't know off-hand, but I can tell you that any time two threads are writing to the same variable (vec->synchronize), you are in for trouble. For synchronization like this, please allow me to recommend pipes or semaphores. Use shared memory only when only one thread writes, or when you use other mechanisms (like semaphores or mutexes) to control access to the shared memory.
If you can't use semaphores, use signals and signal handlers instead. If you can't use signals I can see two other solutions:
Use masks to block all signals when your code is in the critical zone (modifying the shared memory). This way you assure that the data shared memory is not corrupted.
Instead of doing while(vec->synchronize!=1) you should use an atomic function, like Test&Set. The problem with this is that it is pretty hard to implement in software.
Now, the biggest downside of these already not too very good solutions, is that they will not work in multiprocessor systems.
I have a program in which i have a parent process and i want to create 3 children processes.
I also have created 2 shared memories (IN, OUT) and 1 semaphore for each shared memory.
The idea is:
The parent process has 3 integers and has to write in shared memory (IN) one of these integers. Then one of the children processes reads it, does some calculations and writes something in shared memory (OUT) from where the parent reads the result. Then the parent process adds the next integer to the shared memory and so on..
This is part of my code where i try to implement the first part (write-read from shared memory IN):
// create and attach shared memory
memidIN = shmget(...);
memidOUT= shmget(...);
pointerIN = (...) shmat(...);
pointerOUT = (...) shmat(...);
// create and init semaphores
semIN = semget(...);
semOUT = semget(...);
semctl(semIN, ...); // initialize both to 1
semctl(semOUT, ...);
for (i = 0; i < children; ++i)
{
pid = fork();
if (pid)
{
// parent process code
down sem_IN
write in shmIN
up sem_IN
}
else if (pid == 0)
{
// Children processes code
down sem_IN
read from shmIN
up sem_IN
exit(0);
}
else
//ERROR
}
// dont die until childrens die
for( j = 0; j < children; j++)
wait(&status);
The question is, how can i be sure that the children processes read the correct value? I mean if the parent process writes 5 then one process should take it, do something, write something in OUT. Then the parent should write another value, lets say 10.
In my program 5 could be read by the children processes 2 or more times.
Should i use a mutex semaphore to make sure that the children processes read the correct value and to make sure that the parent process updates the value when one of the children has read it?
Any ideas?
So, you can arrange data in you IN shared memory by this way:
int Number;
bool Number_IsRead; // Initialized by 'true'.
When you need to pass a Number, you should do
Number_IsRead = false;
Child should check Number_IsRead before reading Number.
When Number has read, child should assign true to Number_IsRead.
If you have 3 children who need to read Number, you should create 3 flags (bool Number_IsRead[3]).
Also you must use semaphores when you changing Number or Number_IsRead.
P.S. In general it is not a good idea to use shared memory instead of message queues (msgget/msgctl/msgsnd/msgrcv/etc.).
According to the textbook I am reading, the code below creates N child processes that will exit with unique statuses.
/* Parent creates N children */
for (i = 0; i < N; i++)
if ((pid[i] = Fork()) == 0) /* Child */
exit(100+i);
Earlier in the textbook, it states that the following code will have 8 lines of output:
int main(){
Fork();
Fork();
Fork();
printf("hello\n");
exit(0);
}
This leads me to believe that there are 2^n child processes, where n is the number of times fork() is called. Is the reason the first code only produces N child processes (as opposed to 2^N) because the child exits every time, so by the time the subsequent fork() is called, it only operates on the parent process?
Every successful call to fork(), creates a new process.
In the first example, the children processes (the return value of fork() being 0) call exit();, which means they won't call the next fork().
In the second example, every children process continues forking.
When fork() is called it copies the parent data and starts executing from that point individually. So the execution of the parent or child is depend on the scheduling of process. Whichever process get cpu time will be executed whether it is child or parent. We have to take care that which code should run by which process(child or process).