find out which file descriptors share the same "open file description"

What you're looking to compare are the struct file pointers that the file descriptors point to. (Inside the kernel is one task_struct data structure for each thread. It contains a pointer to another structure called the files_struct. And that structure contains an array of pointers, each one to a struct file. It's the struct file that holds the seek offset, the open flags, and a few other fields.)

I don't know of any user-visible way to see the pointers in the files_struct other than the use of some intrusive tools. For example, SystemTap could be given a PID and it could find the corresponding task_struct and follow the pointers. If you're looking for passive, though, I think that's about it. Dell released a tool a long time ago called KME (Kernel Memory Editor) that gave a spreadsheet-like interface to live kernel memory and it could do what you want, but it was never ported to 64-bit. (I tried and never got it completely working, and wasn't sure why.)

One reason you're not finding lsof to be helpful is that it doesn't see those pointers either (but look at the +f option for non-Linux systems). You could theoretically compare all of the fields in the struct file and think the two structures are the same, yet they could still be from separate open(2) calls.

Take a look at the pfiles SystemTap script for ideas. If you modified it to print the address of the struct file, you'd have your solution. You might also check opened_file_by_pid.stp since there's a function in it that walks the files_struct, ie. the file descriptor table, looking at the struct file objects...

Might I ask what you're trying to accomplish?


For Linux 3.5 and onward, this can be accomplished with kcmp(2):

KCMP_FILE

  • Check whether a file descriptor idx1 in the process pid1 refers to the same open file description (see open(2)) as file descriptor idx2 in the process pid2. The existence of two file descriptors that refer to the same open file description can occur as a result of dup(2) (and similar) fork(2), or passing file descriptors via a domain socket (see unix(7)).

The man page provides an example specifically for the use case OP asked. Note that this syscall requires the kernel be compiled with CONFIG_CHECKPOINT_RESTORE set.