|
Home > Archive > Unix Programming > May 2006 > fork and file
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| maxim2k 2006-05-29, 5:32 pm |
| Hi all,
I've a small C program on Linux: the parent will fork a few childs (one
for each client connection from the network) and I need all the childs
to share a common int variable.
Since I'm new to C and this is not a real-world application (so no
concurrency checks needed for access on the shared variable), I was
thinking to use a simple file for writing/reading the common variable,
since I don't feel comfortable using a full-blown IPC implementation
right now (e.g. shared memory).
If I got it correctly, I should open the file in the parent, so all the
childs will have access to it, is that correct?
What function should I use in the parent? fopen or open?
And what abut the childs? fwrite or write?
Should I close (fclose or close) the file in the child before exiting?
I'd appreciate any reply or any link to online resources to learn more
about this topic.
Thanks in advance.
| |
| Gordon Burditt 2006-05-29, 5:32 pm |
| >I've a small C program on Linux: the parent will fork a few childs (one
>for each client connection from the network) and I need all the childs
>to share a common int variable.
How is this variable used? In particular, do you have a one writer,
many readers situation, or many writers, many readers?
>Since I'm new to C and this is not a real-world application (so no
>concurrency checks needed for access on the shared variable), I was
You most likely DO need concurrency checks on the variable
if it's stored in a file (or just about anywhere else).
>thinking to use a simple file for writing/reading the common variable,
>since I don't feel comfortable using a full-blown IPC implementation
>right now (e.g. shared memory).
>If I got it correctly, I should open the file in the parent, so all the
>childs will have access to it, is that correct?
Probably not. Opening the file in the parent before the fork() causes
all the open file descriptors to share a file pointer. This causes
problems when two processes try to use it simultaneously.
A wants to read the variable.
B wants to write the variable.
1. A rewinds the file.
2. B rewinds the file.
3. A reads the file, advancing the file pointer.
4. B writes the file, writing a *SECOND* int after the first one.
B's write has now been ignored. If things happened in a different
order (step 4 before step 3), A could have gotten EOF on its read.
>What function should I use in the parent? fopen or open?
Use of stdio functions is likely to create headaches with buffering.
If you intend doing read-alter-rewrite operations (like incrementing
a counter), you also need file locking, which is made messy with
stdio buffering.
>And what abut the childs? fwrite or write?
>Should I close (fclose or close) the file in the child before exiting?
Checking for errors is a GOOD thing, and difficult if you just exit().
Gordon L. Burditt
| |
|
| maxim2k wrote:
> Hi all,
>
> I've a small C program on Linux: the parent will fork a few childs (one
> for each client connection from the network) and I need all the childs
> to share a common int variable.
>
> Since I'm new to C and this is not a real-world application (so no
> concurrency checks needed for access on the shared variable), I was
> thinking to use a simple file for writing/reading the common variable,
> since I don't feel comfortable using a full-blown IPC implementation
> right now (e.g. shared memory).
>
> If I got it correctly, I should open the file in the parent, so all the
> childs will have access to it, is that correct?
>
> What function should I use in the parent? fopen or open?
>
> And what abut the childs? fwrite or write?
> Should I close (fclose or close) the file in the child before exiting?
>
> I'd appreciate any reply or any link to online resources to learn more
> about this topic.
>
> Thanks in advance.
The easyest way to perform ipc is to use a mmap() ed file.
The mapping is inherited by the children.
The mmunmap is automatically done at exit (though it could be handled in
a neater way ...)
Even for non-related processes, this trick may work, but each
participant has to mmap() the file itself.
Concurency is always an issue.
HTH,
AvK
| |
| maxim2k 2006-05-29, 5:32 pm |
| On 5/26/06 9:17 PM, Gordon Burditt wrote:
> How is this variable used? In particular, do you have a one writer,
> many readers situation, or many writers, many readers?
Many writers, many readers.
> You most likely DO need concurrency checks on the variable
> if it's stored in a file (or just about anywhere else).
Will I have issues w/o currencurrency checks even if there are only a
few clients? Again, this is not a production application.
> B's write has now been ignored. If things happened in a different
> order (step 4 before step 3), A could have gotten EOF on its read.
What about using the pread and pwrite functions? Will they solve this issue?
> Use of stdio functions is likely to create headaches with buffering.
> If you intend doing read-alter-rewrite operations (like incrementing
> a counter), you also need file locking, which is made messy with
> stdio buffering.
IIRC, I should avoid the fopen function then and use the open function
instead, right?
> Checking for errors is a GOOD thing, and difficult if you just exit().
You are right, I meant before returning.
Thanks.
| |
| maxim2k 2006-05-29, 5:32 pm |
| On 5/26/06 9:18 PM, moi wrote:
> The easyest way to perform ipc is to use a mmap() ed file.
> The mapping is inherited by the children.
So I should call the mmap() function before the fork() call, right?
> Even for non-related processes, this trick may work, but each
> participant has to mmap() the file itself.
I'm a bit confused, didn't you say that children inherited mapping
automatically?
> Concurency is always an issue.
Can you give me more info about the issue?
Also, do you have any example about using mmap/fork in the same program?
Thanks a lot.
| |
| Barry Margolin 2006-05-29, 5:32 pm |
| In article <22ec9$4477f99e$5277c1be$9562@news0.easynet.it>,
maxim2k <maxim2k@gmail.com> wrote:
> On 5/26/06 9:18 PM, moi wrote:
>
> So I should call the mmap() function before the fork() call, right?
>
>
> I'm a bit confused, didn't you say that children inherited mapping
> automatically?
Yes, children do. Non-related processes don't, though.
>
>
> Can you give me more info about the issue?
Let's say two processes each try to add 1 to the shared variable. That
works by reading the variable from memory into a register, adding to the
register, then writing it back to memory. Two processes both adding 1
*should* increase it by 2. But without proper mutual exclusion, the
following can happen:
P1: read memory
P2: read memory
P1: add 1 to register
P1: write memory
P2: add 1 to register
P2: write memory
The result is that instead of adding 2, it has only increased by 1.
>
> Also, do you have any example about using mmap/fork in the same program?
There's nothing special about it.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
|
| Barry Margolin wrote:
> In article <22ec9$4477f99e$5277c1be$9562@news0.easynet.it>,
> maxim2k <maxim2k@gmail.com> wrote:
>
>
>
>
> Yes, children do. Non-related processes don't, though.
>
>
>
>
> Let's say two processes each try to add 1 to the shared variable. That
> works by reading the variable from memory into a register, adding to the
> register, then writing it back to memory. Two processes both adding 1
> *should* increase it by 2. But without proper mutual exclusion, the
> following can happen:
>
> P1: read memory
> P2: read memory
> P1: add 1 to register
> P1: write memory
> P2: add 1 to register
> P2: write memory
>
> The result is that instead of adding 2, it has only increased by 1.
Thanks, Barry.
To the OP: this is known as the "lost update" problem.
IIRC it could probably be solved by the bakery-algorithm.
GIYF
>
>
>
> There's nothing special about it.
>
fd = open(...);
ptr = mmap( ..., fd, ...);
pid = fork();
et voila!
AvK
| |
| Gordon Burditt 2006-05-29, 5:32 pm |
| > > How is this variable used? In particular, do you have a one writer,
>
>Many writers, many readers.
>
>
>Will I have issues w/o currencurrency checks even if there are only a
>few clients? Again, this is not a production application.
You can have problems with as few as two read/write clients.
How likely is it that you will have near-simultaneous attempts
to read and write by two clients? This is what causes problems.
If it's a counter and it loses 1% of the counts on average (perhaps
3% on one day and almost none on another), is that acceptable?
Remember that any code can run in 0 CPU time and 0 memory if it
doesn't have to produce the right answer.
>
>What about using the pread and pwrite functions? Will they solve this issue?
Yes, for read-only or write-only operations. You will still
have problems for a read-alter-rewrite operation that's
supposed to be atomic (like a counter).
>
>IIRC, I should avoid the fopen function then and use the open function
>instead, right?
Yes.
Gordon L. Burditt
|
|
|
|
|