Fill in an array with fork() - c

First of all, I surely know there are faster and less overkill solutions to this, but I absolutely need to fill in an array with child processes only.
Let's say I have 3 childs:
int pos = 0;
for (i = 0; i<3 ; i++){
switch (fork()){
case -1: //fork error;
printf("[ERROR] - fork()\n");
exit(EXIT_FAILURE);
case 0: //child
fill(&req, pos);
pos++;
exit(EXIT_SUCCESS);
default:
break;
}
}
where fill basically works like this:
void fill (request *req, int pos){
req->array[pos] = 1;
}
I realized this method of course doesn't work, since every child has a copy of pos = 0, and they just increment their copy, so the array always gets modified at 0.
The struct request is a simpe struct with a pid and a int array to send through fifo.
typedef struct request {
int cpid; //client pid
int array[SIZE]; //array
} request;
What can I do to fill in this array with the child processes only? I have to repeat, I can't use workarounds, just fork() and childs.
Thanks!

If the children are the ones who have to fill the array, then their modifications cannot be seen by the parent or by any other child, unless the parent and the child share some memory (shmget).
Other workarounds include sending all the data to a central process using pipes or any other communication mechanism.

You cannot alter some data (to be shared) after a fork, because each process has -by definition- its own address space, hence any changes to data is private to that process (unless you use shared memory).
You could use shared memory, which you have to set up before the call to fork(2). Then you have synchronization issues. So read shm_overview(7) and sem_overview(7); in your case, I feel it is overkill.
You might also use threads, not processes. Some processes have several threads, all sharing -by definition- the same common address space. Again, synchronization is an issue (e.g. with mutexes). Read some pthread tutorial
You could use some other IPC, e.g. pipe(7)-s. You'll probably want a multiplexing syscall like poll(2).
(I guess, perhaps incorrectly, that the whole point of this homework is to teach you about pipes and event loops; if you use pipes, better adopt some textual protocol)
Read Advanced Linux Programming.
BTW, on fork and other syscalls error, you generally should call perror(3) -not a plain printf like you do- then exit(EXIT_FAILURE).

Related

C unnnamed pipes and fork for calculation

So I'm trying to create program that accepts user input (price for example 50) and then first child passes it to second, second one add 10 (price is now 60), third one then 50 (price is now 110) and 4 one just prints/returns final price. I have fork in loop and I'm creating pipes, but price is always the same, only 10 is added in each child. What is wrong or how to fix so that it's going to work as I want to.
My code:
int main(int argc,char *argv[])
{
int anon_pipe[2];
int n,N=4;
char value_price[100];
if(argc>1)
{
int price=atoi(argv[1]);
printf("%d\n",price);
if(pipe(anon_pipe)==-1){
perror("Error opening pipe");
return -1;
}
for(n = 0; n < N; n++){
switch(fork()){
case -1:
perror("Problem calling fork");
return -1;
case 0:
close(anon_pipe[1]);
read(anon_pipe[0],value_price,100);
price+=10;
sprintf(value_price,"%d \n",price);
printf("Price: %d\n",atoi(value_price));
write(anon_pipe[1],value_price,sizeof(value_price));
_exit(0);
}
}
close(anon_pipe[0]);
sleep(1);
close(anon_pipe[1]);
}
return 0;
}
You seem to think that forking makes the child start from the beginning of the program. This is not the case, forking makes the child start at the same line when the fork() was called
For instance look at this code here:
read(anon_pipe[0],value_price,100);
price+=10;
sprintf(value_price,"%d \n",price);
printf("Price: %d\n",atoi(value_price));
See you increase the value of price but you never read that value form the pipe. So all children will always output +10 to their respective pipe.
You should check the return values of your function calls for error codes. If you had done, you would have detected the error arising from this combination of calls:
close(anon_pipe[1]);
// ...
write(anon_pipe[1],value_price,sizeof(value_price));
Very likely, you would also have detected that many of these calls ...
read(anon_pipe[0],value_price,100);
... signal end-of-file without reading anything. At the very least, you need read()'s return value to determine where to place the needed string terminator (which you fail to place before using the buffer as a string).
As a general rule, it is mandatory to handle the return values of read() and write(), for in addition to the possibility of errors / EOF, these functions may perform short data transfers instead of full ones. The return value tells you how many bytes were transferred, which you need to know to determine whether to loop to attempt to transfer more bytes.
Moreover, you have all of your processes using the same pipe to communicate with each other. You might luck into that working, but it is probable that at least sometimes you'll end up with garbled communication. You really ought to create a separate pipe for each pair of communicating processes (including the parent process).
Furthermore, do not use sleep() to synchronize processes. It doesn't work reliably. Instead, the parent should wait() or waitpid() for each of its child processes, but only after starting them all and performing all needed pipe-end handling. Waiting for the child processes also prevents them from remaining zombies for any significant time after they exit. That doesn't much matter when the main process exits instead of proceeding to any other work, as in this case, but otherwise it constitutes a resource leak (file descriptors). You should form the good habit of waiting for your child processes.
Of course, all of that is moot if you don't actually write the data you mean to write; #SanchkeDellowar explains in his answer how you fail to do that.

How to wait for 2 types of events in a loop (C)?

I am trying to wait on waitpid() and read() in a while-true loop. Specifically, I am waiting for either one of these two events and then process it in each iteration of the loop. Currently, I have the following implementation (which is not I desired).
while (true) {
pid_t pid = waitpid(...);
process_waitpid_event(...);
ssize_t sz = read(socket, ....);
process_read_event(...);
}
The problem with this implementation is that the processing of the second event depends on the completion of the first event. Instead of processing these two events sequentially, I wish to process whichever event that comes first in each iteration of the loop. How should I do this?
If you don't want to touch threading, you can include this in the options of the call to waitpid:
pid_t pid = waitpid(pid, &status, WNOHANG);
As from the manpage for waitpid:
WNOHANG - return immediately if no child has exited.
As such, if waitpid isn't ready, it won't block and the program will just keep going to the next line.
As for the read, if it is blocking you might want to have a look at poll(2). You can essentially check to see if your socket is ready every set interval, e.g. 250ms, and then call read when it is. This will allow it to not block.
Your code might look a bit like this:
// Creating the struct for file descriptors to be polled.
struct pollfd poll_list[1];
poll_list[0].fd = socket_fd;
poll_list[0].events = POLLIN|POLLPRI;
// POLLIN There is data to be read
// POLLPRI There is urgent data to be read
/* poll_res > 0: Something ready to be read on the target fd/socket.
** poll_res == 0: Nothing ready to be read on the target fd/socket.
** poll_res < 0: An error occurred. */
poll_res = poll(poll_list, 1, POLL_INTERVAL);
This is just assuming that you're reading from a socket, judging from the variable names in your code. As others have said, your problem might require something a bit more heavy duty like threading.
The answer of #DanielPorteous should work too if you don't want to use thread in your program.
The idea is simple, not keeping the waitpid and the read function to wait unless they consumes some time to do their operation. The idea is keeping a timeout mechanism so that, if waitpid has nothing to create an impact to the whole operation, it will return immediately and the same thing goes for the read operation too.
If the read function takes very long time to read the whole buffer, you may restrict the reading manually from the read function so that it doesn't read the whole at once, rather it reads for 2 milliseconds and then pass the cycle to the waitpid function to execute.
But its safe to use threading for your purpose and its pretty easy to implement. Here's a nice guideline about how can you implement threading.
In your case you need to declare two threads.
pthread_t readThread;
pthread_t waitpidThread;
Now you need to create the thread and pass specific function as their parameter.
pthread_create(&(waitpidThread), NULL, &waitpidFunc, NULL);
pthread_create(&(readThread), NULL, &readFunc, NULL);
Now you may have to write your waitpidFunc and readFunc function. They might look like this.
void* waitpidFunc(void *arg)
{
while(true) {
pid_t pid = waitpid(...);
// This is to put an exit condition somewhere.
// So that you can finish the thread
int exit = process_waitpid_event(...);
if(exit == 0) break;
}
return NULL;
}
I think that the right tool in this situation is select or poll. Both are doing essentially the same job. They allow to select those descriptors where an input is available. Hence you can wait simultaneously on two sockets for example. However, it is not directly usable in your case as you want to wait for a process and socket. The solution will be to create a pipe which will receive something when the waitpid finishes.
You can launch a new thread and connect it with the original one with a pipe. The new thread will invoke waitpid and when it finished it will write its result to the pipe. The main thread will wait either for the socket or pipe using select.

Forking a child process that does not use it´s own memory copy

What i want to achieve is the following:
Spawn a new childprocess (pchild) that DOES NOT use its own, but the memoryblock from its parentprocess (pparent).
Why i want to achieve this behavior:
Think of multiple tests where the first one leads to segvault.
Normally your process would stop here due to segfault, all the other tests wouldn't be executed anymore. Therefore i want to encapsule each test in its own process.
Main Problem:
Once i spawn a process it gets its own memory copy (well, i'm
aware of the fact that this is not totally true for all OS, due to 'copy on write' technique). Think of e.g. testing tree functionallity where i have a node structure that has two pointers to other nodes. Once i retrieve a node by e.g. using a pipe or some shared memory block those pointers point to an address which is part of the memory block of the pchild and therefore i get a segvault when i try from pparent to get the childnode by following the pointers inside the node structure.
A Thread isn´t usefull, due to the main behavior some OS have once a segfault happens. (Killing child and father due to 'unclear state' ).
What i have so far (only fork testing part):
int main (void) {
// forking
pid_t pid = fork();
if (pid < 0 ) {
// somewhat went wrong
printf("An error occured!");
} else if (pid != 0) { // inside parent
// closing writing end, as not needed
if(wait(NULL)!=0){
printf("Segfault in Child\n");
} else {
printf("Everyone is done!\n");
}
} else {
printf("Child forked");
char *s = (char *)0xDEADBEEF;
*s = 'a';
printf("this probally is never executed due to segfault\n");
}
return 0;
}
Now my idea is to try to let the pchild access the memory segment of pparent only.
I'd welcome any ideas on how to do so.
Greetings,
Lars
Your question isn't very clear, but I think you have an XY problem.
My understanding is that you want to run a series of tests, where each test sees the results of previous tests that succeeded, but not tests that crashed/failed. If this is the case, one approach would be:
fork before each test
Execute the test in the child.
If the test succeeded, have the parent exit or simply wait while the child forks again and executes the next test in its child. If the test failed, have the parent fork again to do the next test.
Another approach might be to keep your data structures only in shared memory allocated by mmap with MAP_SHARED|MAP_ANON, but then if one test left them in an inconsistent state, all future test results would be junk.
Your idea of sharing all memory between processes is technically possible, but it will immediately blow up because they clobber each other's state.
Every process has it's own virtual memory adress space so there is no way to give a RAM adress to another process (well you can send a number, but in another virtual memory address space it will point to different 'real' place).
All you need is another thread. Threads of same process share one virtual memory space.
try to use vfork(); instead of fork();systemcall.
that shares the Resources of parent and child process.

Is it possible to fork/exec and guarantee one starts before the other?

Pretty much as the title says. I have a snippet of code that looks like this:
pid_t = p;
p = fork();
if (p == 0) {
childfn();
} else if (p > 0) {
parentfn();
} else {
// error
}
I want to ensure that either the parent or the child executes (but not returns from) their respective functions before the other.
Something like a call to sleep() would probably work, but is not guaranteed by any standard, and would just be exploiting an implementation detail of the OS's scheduler...is this possible? Would vfork work?
edit: Both of the functions find their way down to a system() call, one of which will not return until the other is started. So to re-iterate: I need to ensure that either the parent or the child only calls their respective functions (but not returns, cause they won't, which is what all of the mutex based solutions below offer) before the other. Any ideas? Sorry for the lack of clarity.
edit2: Having one process call sched_yield and sleep, I seem to be getting pretty reliable results. vfork does provide the semantics I am looking for, but comes with too many restrictions on what I can do in the child process (I can pretty much only call exec). So, I have found some work-arounds that are good enough, but no real solution. vfork is probably the closest thing to what I was looking for, but all the solutions presented below would work more or less.
This problem would normally be solved by a mutex or a semaphore. For example:
// Get a page of shared memory
int pagesize = getpagesize();
void *mem = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if(!mem)
{
perror("mmap");
return 1;
}
// Put the semaphore at the start of the shared page. The rest of the page
// is unused.
sem_t *sem = mem;
sem_init(sem, 1, 1);
pid_t p = fork();
if (p == 0) {
sem_wait(sem);
childfn();
sem_post(sem);
} else if (p > 0) {
sem_wait(sem);
parentfn();
sem_post(sem);
int status;
wait(&status);
sem_destroy(sem);
} else {
// error
}
// Clean up
munmap(mem, pagesize);
You could also use a mutex in a shared memory region, but you need to make sure to create with non-default attributes with the process-shared attribute said to shared (via pthread_mutexattr_setpshared(&mutex, PTHREAD_PROCESS_SHARED)) in order for it to work.
This ensures that only one of childfn or parentfn will execute at any given time, but they could run in either order. If you need to have a particular one run first, start the semaphore off with a count of 1 instead of 0, and have the function that needs to run first not wait for the semaphore (but still post to it when finished). You might also be able to use a condition variable, which has different semantics.
A mutex should be able to solve this problem. Lock the mutex before the call to fork and have the 1st function excute as normal, while the second tries to claim the mutex. The 1st should unlock the mutex when it is done and the second will wait until it is free.
EDIT: Mutex must be in a shared memory segment for the two processes
Safest way is to use a (named) pipe or socket. One side writes to it, the other reads. The reader cannot read what has not been written yet.
Use a semphore to ensure that one starts before the other.
You could use an atomic variable. Set it to zero before you fork/thread/exec, have the first process set it to one just before (or better, after) it enters the function, and have the second wait while(flag == 0).

How to make multiple `fork()`-ed processes comunicate using shared memory?

I have a parent with 5 child processes. I'm wanting to send a random variable to each child process. Each child will square the variable and send it back to the parent and the parent will sum them all together.
Is this even possible? I can't figure it out...
edit: this process would use shared memory.
There are a great number of ways to do this, all involving some form of inter-process communication. Which one you choose will depend on many factors, but some are:
shared memory.
pipes (popen and such).
sockets.
In general, I would probably popen a number of communications sessions in the parent before spawning the children; the parent will know about all five but each child can be configured to use only one.
Shared memory is also a possibility, although you'd probably have to have a couple of values in it per child to ensure communications went smoothly:
a value to store the variable and return value.
a value to store the state (0 = start, 1 = variable ready for child, 2 = variable ready for parent again).
In all cases, you need a way for the children to only pick up their values, not those destined for other children. That may be as simple as adding a value to the shared memory block to store the PID of the child. All children would scan every element in the block but would only process those where the state is 1 and the PID is their PID.
For example:
Main creates shared memory for five children. Each element has state, PID and value.
Main sets all states to "start".
Main starts five children who all attach to the shared memory.
Main stores all their PIDs.
All children start scanning the shared memory for state = "ready for child" and their PID.
Main puts in first element (state = "ready for child", PID = pid1, value = 7).
Main puts in second element (state = "ready for child", PID = pid5, value = 9).
Child pid1 picks up first element, changes value to 49, sets state to "ready for parent"), goes back to monitoring.
Child pid5 picks up second element, changes value to 81, sets state to "ready for parent"), goes back to monitoring.
Main picks up pid5's response, sets that state back to "start.
Main picks up pid1's response, sets that state back to "start.
This gives a measure of parallelism with each child continuously monitoring the shared memory for work it's meant to do, Main places the work there and periodically receives the results.
The nastiest method uses vfork() and lets the different children trample on different parts of memory before exiting; the parent then just adds up the modified bits of memory.
Highly unrecommended - but about the only case I've come across where vfork() might actually have a use.
Just for amusement (mine) I coded this up:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/wait.h>
int main(void)
{
int i;
int array[5];
int square[5];
long sum = 0;
srand(time(0));
for (i = 0; i < 5; i++)
{
array[i] = rand();
if (vfork() == 0)
{
square[i] = array[i] * array[i];
execl("/bin/true", "/bin/true", (char *)0);
}
else
wait(0);
}
for (i = 0; i < 5; i++)
{
printf("in: %d; square: %d\n", array[i], square[i]);
sum += square[i];
}
printf("Sum: %d\n", sum);
return(0);
}
This works. The previous trial version using 'exit(0)' in place of 'execl()' did not work; the square array was all zeroes. Example output (32-bit compilation on Solaris 10, SPARC):
in: 22209; square: 493239681
in: 27082; square: 733434724
in: 2558; square: 6543364
in: 17465; square: 305026225
in: 6610; square: 43692100
Sum: 1581936094
Sometimes, the sum overflows - there is much room for improvement in the handling of that.
The Solaris manual page for 'vfork()' says:
Unlike with the fork() function, the child process borrows
the parent's memory and thread of control until a call to
execve() or an exit (either abnormally or by a call to
_exit() (see exit(2)). Any modification made during this
time to any part of memory in the child process is reflected
in the parent process on return from vfork(). The parent
process is suspended while the child is using its resources.
That probably means the 'wait()' is unnecessary in my code. (However, trying to simplify the code seemed to make it behave indeterminately. It is rather crucial that i does not change prematurely; the wait() does ensure that synchronicity. Using _exit() instead of execl() also seemed to break things. Don't use vfork() if you value your sanity - or if you want any marks for your homework.)
Things like the anti thread might make this a little easier for you, see the examples (in particular the ns lookup program).

Resources