Two kinds of nothing

$ cat < /dev/null
$ cat < /tmp/empty.txt

Assuming /tmp/empty.txt really is empty, are these two invocations different?


Yep, but only slightly:

$ touch /tmp/empty.txt && \
    vimdiff \
      <(strace cat < /dev/null 2>&1) \
      <(strace cat < /tmp/empty.txt 2>&1)

Disregarding memory address allocation differences, the only difference here is the fstat64 call:

$ touch /tmp/empty.txt && \
    vimdiff \
      <(strace -e \!memory cat < /dev/null 2>&1) \
      <(strace -e \!memory cat < /tmp/empty.txt 2>&1)

Raspbian also listed set_tls and cacheflush as system calls that changed, but I couldn't see how to exclude them from strace. (set_tls isn't even in Google search results. 🤔 )


The differences to the fstat64 call:

 fstat64(0, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
  • st_mode=S_IFCHR: Is a character device
  • 0666: Has permissions rw-rw-rw-
  • st_rdev=makedev(1, 3): Refers to /dev/null
    • st_rdev identifies a device ID
    • makedev(1, 3) creates /dev/null (identified by the major and minor IDs of 1, 3)
fstat64(0, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0  
  • st_mode=S_IFREG: Is a regular file
  • 0644: Has permissions rw-r--r--
  • st_size=0: The file size is 0 bytes

Finally, when reading, they have the same function signature:

read(0, "", 131072) = 0  
  • 0: The file descriptor from which to read
  • "": The buffer to which data will be written
    • (I don't know how "" is determined)
  • 131072: The size_t on Raspberry Pi 2
    • (Need to confirm this)