Mailinglist Archive: opensuse-programming (85 mails)
| < Previous | Next > |
Re: [suse-programming-e] The meaning of atomic in write()
- From: Jerry Feldman <gaf@xxxxxxx>
- Date: Fri, 31 Mar 2006 14:23:29 -0500
- Message-id: <200603311423.30256.gaf@xxxxxxx>
On Friday 31 March 2006 1:46 pm, Anders Johansson wrote:
> On Fri, 2006-03-31 at 08:00 -0500, Jerry Feldman wrote:
> > I agree pretty much with your statement.
> > The OP was opening a file for writing, then performing a fork where
> > both the parent and child were writing to the file simultaneously. I
> > took the program that the OP submitted and ran it on SuSE 10 (32-bit),
> > and ran it on RHEL 4 (64-bit IA64). Both had the same successful result
> > without the overwriting that the OP experienced. (In both cases, 2.6
> > kernel).
>
> Are you implying that the file location pointer is shared across a dup()
> call in these systems?
No. A fork(2) clones the parent's environment. Actually, they share the same
memory, but the pages are marked copy-on-write which means that when there
is a change, the page is copied before it is dirtied, so it is has a
similar behavior if the copy operation was done.
What I am implying is that after the fork(2) occurs, and both processes are
writing to the same file, data integrity is maintained. I need to qualify
this a bit more in that the write(2) system call is atomic, but the two
processes data may be interleaved depending on the amount of data.
This is the result I get on both SuSE 10 (32-bit single processor) and a
dual processor IA64 (HP Integrity 1620).
gaf@cedar C]$ cat test.txt
28483: 1
28483: 2
28483: 3
bufsiz=8192 pipe_buf=4096
Parent is process 28482
28482: 1
28482: 2
28482: 3
In the case of dup(2), you are simply making a copy of a file descriptor.
The file descriptors all point to the same open file description, so that:
fd2 = dup(fd1);
write(fd1, buf, count); // writes to the current location, and bumps the
location pointer by count.
write(fd2, buf, count); // Writes to the updated location pointer set
previously.
in this case:
fd1 = open(...);
pid = fork();
if (pid == 0) { // child
write(fd1, ...) // updates location
...
close and exit
} else if (pid > 0) { // parent
write (fd1, ...); // updates location
...
close
wait
exit
} else { // error pid == -1)
report error and exit
}
In the above code, there is a race condition in that either the parent or
the child writes first, so the second data written will be written to a
location beyond where the first data was written. Whether the parent or
child writes first depends on a number of things.
--
Jerry Feldman <gaf@xxxxxxx>
Boston Linux and Unix user group
http://www.blu.org PGP key id:C5061EA9
PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
> On Fri, 2006-03-31 at 08:00 -0500, Jerry Feldman wrote:
> > I agree pretty much with your statement.
> > The OP was opening a file for writing, then performing a fork where
> > both the parent and child were writing to the file simultaneously. I
> > took the program that the OP submitted and ran it on SuSE 10 (32-bit),
> > and ran it on RHEL 4 (64-bit IA64). Both had the same successful result
> > without the overwriting that the OP experienced. (In both cases, 2.6
> > kernel).
>
> Are you implying that the file location pointer is shared across a dup()
> call in these systems?
No. A fork(2) clones the parent's environment. Actually, they share the same
memory, but the pages are marked copy-on-write which means that when there
is a change, the page is copied before it is dirtied, so it is has a
similar behavior if the copy operation was done.
What I am implying is that after the fork(2) occurs, and both processes are
writing to the same file, data integrity is maintained. I need to qualify
this a bit more in that the write(2) system call is atomic, but the two
processes data may be interleaved depending on the amount of data.
This is the result I get on both SuSE 10 (32-bit single processor) and a
dual processor IA64 (HP Integrity 1620).
gaf@cedar C]$ cat test.txt
28483: 1
28483: 2
28483: 3
bufsiz=8192 pipe_buf=4096
Parent is process 28482
28482: 1
28482: 2
28482: 3
In the case of dup(2), you are simply making a copy of a file descriptor.
The file descriptors all point to the same open file description, so that:
fd2 = dup(fd1);
write(fd1, buf, count); // writes to the current location, and bumps the
location pointer by count.
write(fd2, buf, count); // Writes to the updated location pointer set
previously.
in this case:
fd1 = open(...);
pid = fork();
if (pid == 0) { // child
write(fd1, ...) // updates location
...
close and exit
} else if (pid > 0) { // parent
write (fd1, ...); // updates location
...
close
wait
exit
} else { // error pid == -1)
report error and exit
}
In the above code, there is a race condition in that either the parent or
the child writes first, so the second data written will be written to a
location beyond where the first data was written. Whether the parent or
child writes first depends on a number of things.
--
Jerry Feldman <gaf@xxxxxxx>
Boston Linux and Unix user group
http://www.blu.org PGP key id:C5061EA9
PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
| < Previous | Next > |