Understanding the structure of the open file table

I'm trying to understand the structure of the open file table. During this search I'm reading things that look like (for me) they are in contrast with each other.

In a system there is a:

File descriptor table:
This table is located in user space and is associated with a certain process (per-process).

Open file table:
This table is located in kernel space and is associated with all processes (process-wide).

Entries in the file descriptor table point to the open file table. This all is clear. Now let's go to the structure of these tables. For example, see: https://elixir.bootlin.com/linux/v3.18/source/include/linux/fdtable.h#L24

struct fdtable {
        [...]
};

Open in new window


And:

/*
 * Open file table structure
 */
struct files_struct {
        [...]
};

Open in new window


Also this is clear. But now see for example: http://www.andrew.cmu.edu/user/gkesden/ucsd/classes/sp17/cse291-a/applications/ln/lecture5.html

Per Process File Information


struct files_struct { /* kept within task_struct (PCB) */
        [...]
};

Here they are talking about files_struct when it's about "per process file information". I don't understand this, because the open file table is process-wide. This is for example what they are saying:

The count variable tracks the number of files the process has open

But imagine ... two different processes point to the same entry in the open file table. I think "count" only says semething about how many file descriptors are pointing to that entry in the open file table. This has nothing to do with a specific process or something?

This is just an example, because many websites say the same. Another example: https://books.google.nl/books?id=sKoo-cFNPYsC&pg=PA159&lpg=PA159&dq=what+is+"max_fds"

It gets a struct files_structure table for the current process

If the "files_structure" refers to structure of the open file table, then they could not say "for the current process", because the open file table is not about particular processes. Actually they are saying this:

It gets a table for the current process

However, the only table that is per-process is the "file descriptor table" and not the "open file table". So it doesn't make sence to get the open file table for the current process, because for another process it's the same table.

Am I missing something? Or these websites incorrect? And how about "count"? And "struct file" is also part of the structure of the open file table, right? See:


struct files_struct { /* kept within task_struct (PCB) */
        [...]
        struct file * fd_array[NR_OPEN_DEFAULT];
};
Maarten BruinsAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
It is a simple mismatch between terms used in the kernel documentation and lecture text that you linked to. What the kernel (struct files_struct) is calling "Open file table" in the source comments is what the lecture text is referring to as the "per process table" or "Per process file information" and what you are calling "File descriptor table". It is unfortunate that two different texts have used exactly the same name for different concepts, but as long as you can make that jump, you should be fine after that.

A few things to clarify then...

"struct files_struct" and "struct fdtable" aren't two different tables, they are just an implementation detail of this "File Descriptor Table" aka "Per process file information" aka "Open file table" in the kernel source. "struct files_struct" just contains a pointer to the current "struct_fdtable" which is what is really holding the fd_array. It's this last fd_array which you can think of as the real table, as it is the thing that the file descriptors index into to get the "struct file".


Here they are talking about files_struct when it's about "per process file information". I don't understand this, because the open file table is process-wide. This is for example what they are saying:

The count variable tracks the number of files the process has open

Ok, so hopefully, now that you know what I have written above, you should be ok with this... this "count" member IS the number of files the process has open.


But imagine ... two different processes point to the same entry in the open file table. I think "count" only says semething about how many file descriptors are pointing to that entry in the open file table.

Ok, normally this doesn't happen. If two totally separate processes have the same file open, there will be two different entries in "open file table" (as you call it), one for each process. This does get a bit different if the two processes are related and the open file was inherited from the parent, but I would leave that for another day!



And "struct file" is also part of the structure of the open file table, right?

Well, it turns out that that structure is used in both tables... Using your terms, the "file descriptor table" is an array of pointers to "struct file" objects and the "open file table" is (usually) a linked list of pointers to "struct file" objects. And to be complete, even the objects that are of that structure (i.e. the memory where the struct file members are stored) are shared. As noted above, the two tables are just arrays/lists of pointers to these objects, there is only one struct file object for a processes opening of a particular file, and both tables have a reference to this same object.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Maarten BruinsAuthor Commented:
Really really really helpful again, thanks! You nailed it ;).

While I was reading about this subject on the internet, I already noticed that many people use different terms for the same thing (really confusing). Also for example:

per process open-file table    -> file descriptor table
system-wide open file table    -> open file table

Open in new window


If I understand you well, it's just the same open file table. So I have to see it like:

Your open file table (files_struct) consists of:
- struct_fdtable (my file descriptor table)
- struct file (my open file table)

Do I understand this correctly? Many websites say this:


1. file descriptor table -> user space
2. open file table       -> kernel space

But if it's one table, then there is only 1 "location" for that table. However, 1 location always consists of multiple data (e.g. multiple data blocks). So this can be still correct. I just have to see it that a part of the table is "user space" and a part of the table as "kernel space". Is this correct?

And about this:

But imagine ... two different processes point to the same entry in the open file table. I think "count" only says semething about how many file descriptors are pointing to that entry in the open file table.
Ok, normally this doesn't happen. If two totally separate processes have the same file open, there will be two different entries in "open file table" (as you call it), one for each process.

I think now you got confused by the terms ;). How I see/saw it:

file descriptor table -> open file table -> inode/vnode table

If you would fork one "file descriptor table", then both processes (both fd tables) are refering to the same entry in my "open file table". I think maybe you wanted to say (correct me if I'm wrong):

If two totally separate processes have the same file open, there will be two different entries in "file descriptor table" (as you call it)

But with a terminal file (special character file) ... are stdin, stdout, stderr all pointing to the same entry in "my" open file table? (see also: https://www.experts-exchange.com/questions/29120313/How-many-entries-in-the-open-file-table-are-involved-when-it's-about-the-default-terminal-file-descriptors-stdin-stdout-stderr.html)
At least, they could. So then they are also pointing to the same entry in "my" open file table (same as with the fork).

Furthermore, I also think that two file descriptors of two different processes can refer to two different entries in "my" open file table WHILE they are still pointing to one file. What exactly do you mean by the "same open file"? The same entry in my open file table? Or the same entry in my inode/vnode table? I assume the latter? Because one file can for example be opened for reading, while the same file can also be opened for writing. Both will point to the same file, but there are two entries involved in my open file table. (correct me if I'm wrong).

That's why "my" open file table is a confusing term. The inode/vnode table has for each open file an entry. However, the open file table does not. The open file table has for each CONNECTION to a file an entry. For example one "read connection" and one "write connection". So actually I think anyway it's better to see "my" open file table as an "file connection table". I think "open file table" (the one I'm using and many websites do) is a bit misleading. Especially with this in mind:

file descriptor table -> open file table -> inode/vnode table
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
I want to draw you a diagram that I think should help straighten a lot of this out, but I can't do this until tomorrow, so I will get back to you. But generally I think you are getting closer!

A couple of things though that I can say/ask now... Basically, all these tables/structures that we've talked about are kernel space objects. The only link to user space is the FD number.

Also, now you have used a term "inode/vnode table", but what exactly are *you* referring to here?
0
Protecting & Securing Your Critical Data

Considering 93 percent of companies file for bankruptcy within 12 months of a disaster that blocked access to their data for 10 days or more, planning for the worst is just smart business. Learn how Acronis Backup integrates security at every stage

Maarten BruinsAuthor Commented:
Thanks a lot again!! Then I'll wait till tomorrow (or another day when you have more time).

So the FD number is indeed the only one in user space. Then indeed I have to see *your* open file table partially (small part, fd "column) as user space, and the rest as kernel space.

And good you're asking about the "inode/vnode table", because I also have a problem with that ;). How you would call my inode/vnode table? The problem is that people are usually talking about THE inode table, but if I understand everything good, then there are two different inode tables:

1. The inode table in memory: this table only contains the inodes of the open/active files? So it's some caching mechnism to speed things up?
2. The inode table that contains all the inodes.

I already opened another post about that yesterday: https://www.experts-exchange.com/questions/29120443/What-is-the-purpose-of-the-inode-table.html This question was about the in memory inode table, but suddenly people started to talk about the "non-kernel" inode table. So probably they are also not aware enough that there are two different inode tables? But I don't really understand this for 100% yet, but probably you do ;).

I'm always reading a lot of different sources before I consider something as correct, so the term "inode/vnode table" is used on many websites.
See: https://en.wikipedia.org/wiki/Inode

The operating system kernel's in-memory representation of this data is called struct inode in Linux. Systems derived from BSD use the term vnode, with the v of vnode referring to the kernel's virtual file system layer.

So probably people are calling it the inode/vnode table because different systems use different names?

Some examples:

- See: https://www.usna.edu/Users/cs/wcbrown/courses/IC221/classes/L09/Class.html
  In the last picture on that page you will see "inode/vnode"

- See: http://lijubjohn.com/index.php/2017/02/04/file-descriptor-and-inode/
  Here they call it the vnode table (Notice that this picture is wrong about the kernel space. The file descriptor table must be in user space.)

- See: http://www.wikiwand.com/en/Inode#/Details
  Here they call it inode table.

- You can search for "file descriptor table" in Google images. Then you will see a lot of inconsistency.

So three examples, three different terms: inode table, vnode table, inode/vnode table. I'm getting a little bit crazy of all the different things I'm reading ;). Hopefully you can explain this.

But if Linux calls this the "inode table", then how the inode "table" outside the kernel/memory is called? If you restart the computer, then in memory inodes are gone, so they must be stored somewhere else too?
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
So the FD number is indeed the only one in user space. Then indeed I have to see *your* open file table partially (small part, fd "column) as user space, and the rest as kernel space.

I wouldn't even think that it is like this, there is NO part of anything in user space, it is entirely in kernel space, eg.

int fd = open("/a/file", O_RDWR);

The only part of the above that deals with user space (other than the area of memory that would be holding the filename string) is 1 integer variable that holds the file descriptor NUMBER that the kernel mode code returned to you. It is no table, just one int holding one number. When you want to read from this file, you make a system call to kernel mode code, passing this one number. It is in kernel space that the file descriptor table in looked up based on this number to return the "struct file" entry.

See: http://lijubjohn.com/index.php/2017/02/04/file-descriptor-and-inode/
  Here they call it the vnode table (Notice that this picture is wrong about the kernel space. The file descriptor table must be in user space.)

So hopefully, now you will realise that this picture is in fact correct!

As for inode/vnode table, while I can't be sure of the details, I think that there might not be any table per se. Just a collection of "struct inode" objects residing in memory that are pointed to by either/both of the "struct file" open file table entries and the dcache dentries.

Hopefully, the diagram that I am working on could make this clearer.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Oh, and just in reference to your earlier post...

I think now you got confused by the terms ;)

If you would fork one "file descriptor table", then both processes (both fd tables) are refering to the same entry in my "open file table". I think maybe you wanted to say (correct me if I'm wrong):

If two totally separate processes have the same file open, there will be two different entries in "file descriptor table" (as you call it)

I think you missed the very first part of the comment that I made... I said "If two totally separate processes have the same file open", so therefore my comment had nothing to do forking at all. What I meant was say that one process, say a web server, has a file open, it could be it's configuration file "/etc/apache/httpd.conf", and then a totally different process, say a bash shell is looking at that same file, by a "cat /etc/apache/httpd.conf". Now these processes did fork from each other in any way, they are separate processes. In this case my comment stands, even though it is the same file, there is still TWO different entries in the "open file table".
0
Maarten BruinsAuthor Commented:
You're amazing again! ;) You're right! I was thinking the wrong way. I was thinking this:

------------------
Something in kernel-space can not be accessed by a user. A user somehow has to come into the "file descriptor table". The fd integer is known in user space, so it needs to have at least access to the column with fd's in the fd table.

user  |   kernel
_______________________________
      |
fd    |   fd column of fd table
      |

Open in new window


This is how you want to see it, but then it's impossible to access the fd table/open file table, because there is a line/door in between. So at least a part of the fd table must be in user space. This acts as the connection between the fd integer and all the other tables in kernel space.

So if all the tables are kernel-space then it's impossible to access them, because a user can not access kernel-space.
------------------

But my mistake was that a user CAN have access to the kernel space. That's why you have system calls. It's just a way to give a user access the kernel-space. Thanks a lot for this, really helpful!!! Many websites on the internet make this mistake (that's why I made this mistake in the first place). For example, see:

https://www.google.nl/search?q=file+descriptor+table&source=lnms&tbm=isch&sa=X&sqi=2&ved=0ahUKEwiGua-k--7dAhUGlJAKHfaGC5wQ_AUIDigB&biw=1920&bih=979#imgrc=C5O4FMX_ovjVgM:

https://www.google.nl/search?q=file+descriptor+table&source=lnms&tbm=isch&sa=X&sqi=2&ved=0ahUKEwiGua-k--7dAhUGlJAKHfaGC5wQ_AUIDigB&biw=1920&bih=979#imgrc=DmjQRep-SBF9QM:

I can go on for a while with websites like that. They put the fd table in user space, but this is incorrect.

Now about your other post:

I said "If two totally separate processes have the same file open", so therefore my comment had nothing to do forking at all.

This sounds weird to me. For example, see: http://www.rozmichelle.com/pipes-forks-dups/#attachment_7363

That's one picture before the fork (parent process) and one picture after the fork (parent process, child process). So by forking, two different processes do have the same file open?
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Yeah, those two images that you link to are incorrect.


As for this...

This sounds weird to me.

I don't know how else to say it, but you are missing the point... I say...

so therefore my comment had nothing to do _with_ forking at all.
(Sorry I missed the _with_ in the original comment, I hope that is not why you missed my point)

And then you go on to say (again)...

fork (parent process) and one picture after the fork (parent process, child process).

you are talking about forking again.

I am NOT talking about forked parent/child processes. I am talking about two processes that have NOTHING to do with each other, and are not inherited from one or the other. I tried to give an example... one process, a web server, that would have been started by the system just after boot up, and another process, a "cat" process started by a shell program after a user typed the command into the shell. So NOTHING to do with each other.

Do you get what I am talking about now?
0
Maarten BruinsAuthor Commented:
Thanks a lot again! I think I understand what you mean. Your quote:

Ok, normally this doesn't happen. If two totally separate processes have the same file open, there will be two different entries in "open file table" (as you call it), one for each process.

Actually you just mean "two different main processes"? I saw a child process and a main process also as two separate processes (that's why I started to talk about forking), but I think you don't see that as two separate processes.

But this is really useful to me, because I've never realized this before. Anyway it's possible that two totally separate processes have the same file open: same offset, same mode (e.g. reading), et cetera. But apparently then there are still two different entries in "my" open file table?

So actually it's possible to have two exactly the same rows in the open file table with exception of the index, is this correct? Two programs can open the same file for the same purposes (same offset/flags et cetera).

I still don't see 100% why it's like that, because if two programs/two processes want to open a file for exactly the same purposes (ofsset, read/write etc.) ... why they just don't use the same entry in "my" open file table?  If one is for example reading and the other one is writing, then I understand that there are two entries. Also if the offset is different, then I also understand it.

Now I'm typing this, maybe I already know the answer. What if one program (A) writes to a file and stops writing at offset 30. Then the other program (B) wants to start writing at offset 0. But, because they are sharing the same entry in the open file table, program "B" starts to write at offset 30 instead of o. This is not what you want. Did I answer my own question correctly? ;)
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Yeah,I think in a round about way you eventually answered your own question. I think it is even easier to understand when thinking about reading a file. If 2 processes opened the same file and then shared the open file entry (and subsequently the offset) then when one process read say 10 bytes of the file, the offset would be moved along by 10. Then the other process gets a time slot to run and it attempts to read 10 bytes, it would get the next 10 bytes of the file,not the first 10 (and the offset moves another 10). Then the first process gets another chance to run and tries to read the next 10 bytes, but the offset has moved so it misses the 10 bytes read by the other process, and just gets the next 10. You should be able to see that each process would only receive bits and pieces of the file.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Just to add another point, hopefully it helps and doesn't confuse things further ;)

Even within just one single process, it could have the same file open twice, and have two different FD's that point to two different open file table entries.

Basically, anytime program code issues a "open" system call (or its variants) a new open file table entry will be created, even if it is for the same file that might be open elsewhere. And also basically, the only time when these entries gets "shared" is any time a dup, dup2 or fork system call is executed.
0
Maarten BruinsAuthor Commented:
Thanks a lot mccarl! And your last post doesn't confuse:

Even within just one single process, it could have the same file open twice, and have two different FD's that point to two different open file table entries.

Just think of the terminal-file and fd 0,1,2. They usually have the same file open...even more than twice (three times: stdin, stdout, stderr) and they have three different fd's pointing to the same file. I don't really understand WHY they can also have three different entries in the open file table, because if one is "read" and the other two are "write", then the offset problem (as discussed above) is not there, so you could have 2 entries in the open file table (one for the two writes, and one for the one read). But that's the discussions of:

https://www.experts-exchange.com/questions/29120313/How-many-entries-in-the-open-file-table-are-involved-when-it's-about-the-default-terminal-file-descriptors-stdin-stdout-stderr.html#a42699516

But anyway, if I keep seeing it like that, then I still have two different fd's (0 read and: 1 or 2 write) pointing to two different open file table entries (within one process). So anyway the quote above doesn't confuse me, because in such a case it's possible.

You still want to draw the diagram?

I want to draw you a diagram

Or you think it's not really necessary anymore? Anyway I think everything you said in this topic is pretty clear to me and it was really helpful. If you're not planning to daw the diagram anymore, I think I can close this question and mark the correct answer? Just let me know.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Instead of the diagram (which with my drawing skills wouldn't have been great), hopefully the analogy I gave in your other question is just as good (if not better). So if you are happy with that, I'm happy if you close out this one.
0
Maarten BruinsAuthor Commented:
Yes! Everything is clear I think, so I've just closed the question. Thanks a lot!!!!
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
You're welcome!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux

From novice to tech pro — start learning today.