For Programmers: Free Programming Magazines  


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]

 

Author fork and file
maxim2k

2006-05-26, 7:04 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-26, 7:04 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
moi

2006-05-26, 7:04 pm

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-27, 4:09 am

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-27, 4:09 am

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 , 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-27, 8:03 am

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 , 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 ***
moi

2006-05-27, 7:02 pm

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-27, 7:02 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
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com