Modify global variable from child process in Linux
I come from a C# background and I have a bit of a tough time with concurrency in C. I am not going to lie to you... This is part of a project I have to do for school. Although professionally I have worked with high level languages, my senior thesis professor threw us under the bus by forcing the entire class to code in C (which most of us have little to no experience with... :( ).
Either case, back to the problem. I have a global integer variable (starting from 0) which needs to be simultaneously incremented by 5 processes until it reaches 100 (100% rather).
Basically what's happening is that instead of individually modifying the completionCounter each child process is making a copy of it...
Is there a lock(object)
or something of the sort as it is available in C#? I tried u开发者_如何学JAVAsing a binary semaphore but I couldn't get it to work, i haven't played with shared memory yet.
const int THREADCOUNT = 5;
int completionCounter = 0;
int main(int argc, char **argv)
{
int count = 0;
pid_t pid;
for(count = 0; count<THREADCOUNT; count++)
{
if( (pid = fork()) < 0 )
{
//error...
return -1;
}
else if( pid == 0 )
{
//child;
while(completionCounter != 100 )
{
printf("[%i] process downloading data chunk...", getpid());
//do stuff here
completionCounter += 5;
}
}
else
{
//parent.
}
}
}
Child processes do not share variables with their parents. The only way you can do this with forked child processes is by specifically creating and mapping shared memory to hold the value.
A more reasonable way to do this would be to use threads rather than child processes, but it seems like you're stuck with the assignment you were given. In that case, I would recommend something like:
int *x = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
before forking, then incrementing *x
in the child processes...
BUT!
Now you have to deal with synchronization. As-is, you'll easily get missing or duplicate numbers in your output. Lookup POSIX process-shared mutexes to get you started in that direction...
This is not being caused by a contention issue, it's the fact that when creating a new process (which is what happens when using fork
), a new copy of the memory space is created. This means in effect that you are creating 5 completionCounter
s -- one for each process. Look into using pthreads if you want everything to share the same memory space.
You are absolutely right, what you want can be achieved using semaphores. Try man 3 sem_wait
, there's an example there.
精彩评论