John Steele Scott
2018-05-01 10:38:50 UTC
***@citra:/tmp$ touch --version | head -1
touch (GNU coreutils) 8.25
***@citra:/tmp$ strace -ttt touch foo 2>&1 | tail -9
1525170579.952032 open("foo", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
1525170579.952080 dup2(3, 0) = 0
1525170579.952119 close(3) = 0
1525170579.952156 utimensat(0, NULL, NULL, 0) = 0
1525170579.952209 close(0) = 0
1525170579.952257 close(1) = 0
1525170579.952294 close(2) = 0
1525170579.952333 exit_group(0) = ?
1525170579.952450 +++ exited with 0 +++
My analysis from that discussion:
It's a historical artifact.
The open()+dup2() pattern comes from the fd_reopen() function, which is used
by several of the programs in the coreutils code base.
Prior to coreutils commit e373bb1, fd_reopen() did not do open()+dup2(), but
closed the desired file descriptor before opening a new one. This was the
case when touch started using this function at coreutils commit 478bd89. Per
that commit message, the intent was to reduce the number of file descriptors
touch would have open.
In the scheme of things the extra call to dup2() is not a big deal. We've lived
with it for 10 years. On my laptop it would take 25,000 invocations of touch
before those unnecessary dup2() calls add up to a second. But touch is called a
lot, on systems all over the world. So maybe you guys care about this?