Is the write(2) system call atomic
Jerry Feldman
gaf at blu.org
Fri Apr 7 14:23:31 EDT 2006
There has been some discussion on another list regarding the write(2) system
call on Linux.
Here is a short code fragment to illustrate where the parent process creates
and opens a file for writing, then forks a child. it was my impression that
the kernel maintains a single structure for each open file. If that is true
then we would see all 6 lines. In most of the failure cases we see that the
first line and part of the second line of the parent are overwritten by the
child.
Note that I would probably use lockf(3), flock(2), or fcntl(2).
fd = open(<filename>, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if ((pid = fork()) > 0) { /* Parent code */
sprintf(buf, "Parent first line\n");
sprintf(str, "Parent is process %d\n", getpid());
for (i=0; i < 2; ++i) {
sprintf(str, "----P=%d: %d\n", getpid(), i);
strcat(buf, str);
} else if (pid == 0) { /* child */
for (i=0; i < 2; ++i) {
sprintf(str, "****C=%d: %d\n", getpid(), i);
strcat(buf, str);
}
} else assert(0); /* error on fork() */
assert(write(fd, buf, strlen(buf)) == strlen(buf));
assert(close(fd) == 0);
if (pid) /* parent wait for child */
wait(NULL);
return 0;
}
In the above case, we observed that on an SMP system, 2.6 kernel that in
some cases the child data overwrote some of the parent data. This should
create a file containing something like:
****C=19585: 0
****C=19585: 1
Parent first line
Parent is process 19584
----P=19584: 0
----P=19584: 1
But in the failure case, the following result may be present.
****C=18099: 0
****C=18099: 1
ocess 18098
----P=18098: 0
----P=18098: 1
--
Jerry Feldman <gaf at blu.org>
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
More information about the Discuss
mailing list