How the "open file table"-entries look like for stdin, stdout, stderr?

Maarten Bruins
Maarten Bruins used Ask the Experts™
on
By default, the first three rows of a "file descriptor table" consists of:

FD 0 (standard input,  associated with keyboard)
FD 1 (standard output, associated with screen)
FD 2 (standard error,  associated with screen)

Open in new window


These file descriptors point to one or more rows in the "open file table". Imagine we only have these three file descriptors. Then how does the "open file table" look like?

Usually all three file descriptors point to the same file, but that doesn't mean they point to the same entry in the "open file table". So how the open file table looks like?

_ | offset | reference count | permissions | flags | pointers
_ |    ?   |        ?        |      ?      |   ?
possible more rows

Open in new window


The lsof command shows for example:

lsof        721    root    0u      CHR              136,1       0t0          4 /dev/pts/1
lsof        721    root    1u      CHR              136,1       0t0          4 /dev/pts/1
lsof        721    root    2u      CHR              136,1       0t0          4 /dev/pts/1

Open in new window


The file "/dev/pts/1" is CHR (character special file). They all point to the same file.
I'm also wondering why it's for example "0u" and not "0r"? The file descriptor 0 stands for input, so it only has to read something.

r for read access;
w for write access;
u for read and write access;

Open in new window


I would expect something like: 0r, 1w, 2w instead of 0u, 1u, 2u? And what are the offsets et cetera?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
nociSoftware Engineer
Distinguished Expert 2018

Commented:
Every process has an open file table  there the FD is an index into.

fd =0 is the first entry, fd=1 the 2nd .... This table holds pointer to a central file table in the OS...
the fd[0] , fd[1] & fd[2] should all point to the same central entry...
And a unit that is both r &w open is effectively updatable entry.

so    central_table[fd[0]] holds the core data.  Implementation varies to Unix used.
All IO is done through the central table. so multiple processes can send data more or less consistently.

For linux you can start here:
/usr/src/linux/include/linux/fdtable.h

And all source files that includes this one.
Duncan RoeSoftware Developer

Commented:
And what are the offsets et cetera?
136/1 are the major and minor device numbers for the special file /dev/pts/1. Try: ls -l /dev/pts
nociSoftware Engineer
Distinguished Expert 2018

Commented:
All devices are in tables,   the major device number indexes the table, the minor (2nd) part of the device number tells the driver which subunit it concerns.   CHR 136,1   means: lookup in Character_device_table[136] for dev_open, dev_close, dev_read, dev_write & dev_control functions and pass them the unit #1.
(/dev/null & /dev/zero share the same character device driver #1, with subunits #3 & #5 respectively)

For block devices there is a similar table the block_device_table, the minor unit numbers are also used to identify partitions.

(then there are sockets, symlinks, hardlinks, named pipes).
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
@noci: I think you're wrong. Not every process has an "open file table". Every process has a "file descriptor table" (user space). The fd's are indexes in this table, but the the "open file table". The rows in the "file descriptor table" refer to a row in the "open file table". Different processes can refer to the same entry in the "open file table". The open file table is located in kernel space.

@Duncan: See: https://cseweb.ucsd.edu/classes/sp16/cse120-a/applications/ln/lecture15.html


The open file table contains several pieces of information about each file:

- the current offset (the next position to be accessed in the file)
- a reference count (we'll explain below in the section about fork())
- the file mode (permissions),
- the flags passed into the open() (read-only, write-only, create, &c),
- a pointer to an in-RAM version of the inode (a slightly light-weight version of the inode for each open file is kept in RAM -- others are on disk), and a structure that contains pointers to all of the .
- A pointer to the structure containing pointers to the functions that implement the behaviors like read(), write(), close(), lseek(), &c on the file system that contains this file. This is the same structure we looked at last week when we discussed the file system interface to I/O devices.

Are we talking about the same stuff? With the next position to be accessed in the file I'm more expecting something like a line-number or line-number/position on that line ... or something like that. But in the other topic you already said that all three fd's refer to the same entry in the "open file table", so then I would expect an offset of 0 for all these three fd's?

So actually I can see the screen/keyboard as a special character file. It's just a stream of data. Is that why it can be the same file? First I need to write something on my keyboard before getting any output or error code. Because it doesn't happen at the same time, later on the same file can be used to pass the output and/or error message? That also means that the output and error message are never using that special file atexactly the same time. Is this correct thinking of me?
nociSoftware Engineer
Distinguished Expert 2018

Commented:
The "open" file table are all entries in the Process private FileTable that are marked open... so yes there is a filetable,  and it keeps state.
Empty slots will be reused from the low numbers up.   (After closing fd == 0, the next FD that will get opened is #0.)
The central "open" file table is more or less the same as the Process one... there is a  global filetable and some entries are marked busy....
Multiple process entries can all reference the same slot in the global table.

Sorry if that distinction wasn't clear.

Author

Commented:
No problem ;). But this all I already knew, but that was not my question ;). I know what a "file descriptor table" is and what a "open file table" is. But my question is specifically about stdin, stdout, stderr pointing by default to the terminal. How the "open file table" entries look like for these three default file descriptors?

From Duncan I already know that they are pointing to the same entry in the "open file table". These entries have i.a. the following columns:


- the current offset (the next position to be accessed in the file)
- a reference count (we'll explain below in the section about fork())
- the file mode (permissions),
- the flags passed into the open() (read-only, write-only, create, &c),

So what are these values when it's about stdin, stdout, stderror (terminal)? In other words, how the "open file table" looks like for the default stdin, stdout, stderror? The "file descriptor table" points to these entry/entries in the "open file table".
nociSoftware Engineer
Distinguished Expert 2018

Commented:
For the OS stdin/sdtout/stderr are nothing special.... They are special by there respective definition fd[0] , fd[1], fd[2].

When a program is called with program >file then the stdout (aka fd[1]) is closed and a new "file" is created and opened for output on fd[1].  There is no need for special handling... For "daemon" processes or background servers  the fd[0].. fd[2] are all closed and opened to /dev/null.

It is the SHELL that make the handling of FD's 0, 1 & 2 special.  Although some shells can also handle other FD's (bash for example).

Author

Commented:
I know that already ;), but that's not my question. I'm talking about how the "open file table" exactly looks like for the default stdin, stdout, stderror (when it's by default pointing to terminal).

You're talking about closing stdout (fd 1 indeed). Then it's not the default anymore. So maybe you have to read the question again. It's about this:


- the current offset (the next position to be accessed in the file)
- a reference count (we'll explain below in the section about fork())
- the file mode (permissions),
- the flags passed into the open() (read-only, write-only, create, &c),

What are they for the default stdin, stdout, stderr...
nociSoftware Engineer
Distinguished Expert 2018

Commented:
Like i said you inherrit them from the SHELL, so what the shell sets up is what they have as settings.
(either as a duplicate from the parent process, or setup by the shell's command line processing)

if you make a shell program yourself you can check that.

main() {
   while (gets(buffer)) { 
      if ((child = fork())  == 0) {
                     /* here stdin/stdou/stderr can be manipulated to what ever */
           exec("/bin/bash", "bash","-c", buffer, 0);    /* official: split the command line yourself into command  & 
                                                                        arguments and also find the path of the program, a shell "SHOULD" pass on stdin/stderr as is */
           exit(127);
      } else {
          int stat; /* receive the exit status */
          wait(&stat);/* Wait for child */
      }
   }
}

Open in new window


The shell doesn't "open" the device unless > < etc are used.
what you can try  is in the above code to open a file and seek to some position and then run a program....

main() {
   char *buffer = "/bin/cat";
      if ((child = fork())  == 0) {
                     /* here stdin/stdout/stderr can be manipulated to what ever */
           close(0);
           if (open("input.txt",0) == -1) {      /* try to open file "input.txt")  */
               puts("input.txt\n");
               exit(100);
           }
           lseek(0,1024L, 0);  /* set file offset to 1024... */
           execl(buffer,buffer,0);     /* here the "RUNNING" program, this one is replaced with /bin/cat */
           exit(127);                 /* or if it fails we end here.... */
      } else {
          int stat; /* receive the exit status */
          wait(&stat); /* Wait for child */
      }
   }
}

Open in new window

These are examples, you will need to declare everything properly.... & include files and have
You can open the "stdin" file with 1 or 2 ... instead...
Same holds for  devices.
So there is no "global" default....

Author

Commented:
Then let me ask the question differently, how does the "open file table" look like for stdin, stdout, stderr for the bash shell (by default)?

Because I think the columns below do not depend on the shell being used:


- the current offset (the next position to be accessed in the file)
- a reference count (we'll explain below in the section about fork())
- the file mode (permissions),
- the flags passed into the open() (read-only, write-only, create, &c),

the current offset: All three file descriptors are using the same character special file, so probably it's 0? Then it doesn't matter which shell is used.
reference count: If fd 0,1,2 would refer to the same entry in the "open file table", then the reference count is 3. This 3 is not inherited from the shell like you're saying.
file mode (permissions): Probaly read/write (u), but at least they do not depend on the shell.
flags: ?

Your answer is incorrect for sure, because for example the value of "reference count" depends on how many file descriptors are pointing to that entry in the "open file table". This value will not be inherit from the shell. This value (reference count) is probably by default 3. This doesn't depend on the shell that will be used. But I'm not sure about all of this, that's why I'm asking the question.
nociSoftware Engineer
Distinguished Expert 2018

Commented:
A device doesn't have an offset. The offset is the current position in the file....

The reference count is an OS INTERNAL integrety mechanism...   The fork()  service must account for this.
That initialises a new process slot.  copies all open file descriptors from one process to the next (verbatim..., including the gaps for closed files).
During the copying of the FD from process parent to the child, the increment is done....,  nothing a shell or any other program can do about it.
if a reference count in the global tables reached 0 all resources can be freed, buffers, etc. etc.. That will happen when ALL programs have closed that specific file.   But the "position"/"offset: in the file  is done by the LAST IO on any file item.
No  de default is NOT 3, considder having background processes:
(your process already has 3....) then
$ ls -l &   #(Will add 3, during forking)
$ ls -l >/tmp/whatever-ls & #( will add 2 for stding & stderr, and add 1 for /tmp/whatever done by shell.)
$ vi /tmp/whatever-vi #(will add 3, during forking)
Closing vi will subtract 3, the ending of the ls -l  will subtract 3 ...

Author

Commented:
I know a device doesn't have an offset. The "open file table" is about files/resources, so I never said it's about a device? So what's the offset in case of a bash shell?

And about the "reference count" ... that's exactly what I'm already saying. In the end it's about how many file descriptors are pointing to the associated entry in the "open file table". So now you're also saying:


nothing a shell or any other program can do about it.

One post before you were saying that these values are inherited from the shell. In my previous post I just explained you that this is incorrect.

And we're talking about the "default", so from the the start (of course also after a i/o redirect or something it's a different situation). So your last examples are irrelevant.

So still the same question for you. In case of:

- bash shell
- default stdin, stdout, stderr (terminal)

how the open file entry/entries looks like for stdin, stdout, stderr. And especially these columns:


- the current offset (the next position to be accessed in the file)
- a reference count (we'll explain below in the section about fork())
- the file mode (permissions),
- the flags passed into the open() (read-only, write-only, create, &c),

That's the question ;). And "by default" you also have to see "from start", because of course later on everything can be changed (i/o redirects et cetera).

Author

Commented:
Oh and about:

But the "position"/"offset: in the file  is done by the LAST IO on any file item.

We're talking about data of a "special character file" in the "open file table". It's about the "terminal file". It's not about just writing to a regular file.

See also:


So actually I can see the screen/keyboard as a special character file. It's just a stream of data. Is that why it can be the same file? First I need to write something on my keyboard before getting any output or error code. Because it doesn't happen at the same time, later on the same file can be used to pass the output and/or error message? That also means that the output and error message are never using that special file atexactly the same time. Is this correct thinking of me?
nociSoftware Engineer
Distinguished Expert 2018

Commented:
Shell doesn't manage reference counts... but it DOES setup which files / devices are assigned to which FD.
the forking / closing / opening of files are the actions done by a shell, and ultimately the  exec*() function will replace the currently running program with the one mentions inheriting all settings as left by the parent.

Files / devices...., that is behind the "global file table"...,  every device needs a "file" entry in some place. Commonly this is /dev/...
On a disk inodes are used to describe objects. Those objects can be "regular"-files or  directories, sockets, symlinks, hardlinks, or "device" nodes.
(those are made by mknod) two types character devices or block devices.  ls -li  shows the various items..
inode#   type-protectionmask  refcount size date name
tXXXXXXXXX     where t = file/device type and XXX are rwx group for allowed    access
- = regular file
s   socket
l symlink
d   directory file
c   Character device in place of size the major/minor device indexes are shown
b   Block device in place of  size are the major.monit device indexes.

The type of file or device determines which set op xxx_open, xxx_close, xxx_read, xxx_write etc are used to handle aspects of IO.

For hardlinks multiple files will show the same inode on the same devices.
For example  . && .. the names are hardlinks to current and paret directories  any file that has refcount != 1 has mulitple names (hardlinks).
refcount == 0 is an empty inode.

For the behaviour of bash... please download the  sources: http://tiswww.case.edu/php/chet/bash/bashtop.html
Bash is rather complicated and the actions taken do depend on the system (MINIX, Linux, OpenVMS, HP-UX) it is compiled for.
Checkout redir.c for handling of files....
    redir_open, noclobber_open()) source files.    nothing special here
     the redir_special_open is for handling of special names..., like if /dev/fd/100 use fd=100 etc. /dev/stdin is used :   (in f.e </dev/stdin) #0 is used instead

Special device handling (if done) is done using ioctl calls.    ioctl is only used in jobs.c (jobs control handling, backgrounding, foregrounding etc.)


The difference between a regular file and a character device file (block devices are really a different thing...)
For a regular file there is a current position which can be manipulated using lseek, and some for manipulating ACLs and protection masks.

For devices also the ACL and protection mask settings besides that there are bits like settings for cooked/raw   number of rows/columns etc. those are managed using ioctl calls. not regular read/writes. in stead of a current position.
You can view those with stty program or ioctl() calls.

Author

Commented:
Everytime you're explaining all kind of things that I'm not asking for ;). I know how the Linux structure is, different file types et cetera et cetera.

Probably these columns (the values I'm asking for):


- the current offset (the next position to be accessed in the file)
- a reference count (we'll explain below in the section about fork())
- the file mode (permissions),
- the flags passed into the open() (read-only, write-only, create, &c),

do not depend on bash. I just gave you an example with "reference count". You can also execute the following command:

lsof | grep "bash"

Open in new window


then you will something like this:

bash      15220    root    0u      CHR              136,1       0t0          4 /   dev/pts/1
bash      15220    root    1u      CHR              136,1       0t0          4 /   dev/pts/1
bash      15220    root    2u      CHR              136,1       0t0          4 /   dev/pts/1

Open in new window


So you don't need to check bash to know it's read and write (u). All three are pointing to the same file (dev/pts/1), so probably all the three df's are pointing to the same entry in the "open file table". Then bash has by default one extra file descriptor:

bash      15220    root  255u      CHR              136,1       0t0          4 /     dev/pts/1

Open in new window


This is always 255 and bash uses this for redirects. So the correct answer has probably to be a reference count of 4. But on purpose I didn't say anything about the fourth one, so I can test a little bit if people explain me the correct things and they really know what they are talking about. But I want to hear it from someone who really know these things. And I'm not sure about all the values, so that's why I'm asking.
nociSoftware Engineer
Distinguished Expert 2018

Commented:
heading for  lsof:

COMMAND     PID   TID       USER   FD      TYPE             DEVICE   SIZE/OFF       NODE NAME

So the 4 is the node./inode ...
This will show all options for lsof https://linux.die.net/man/8/lsof

And this is lsof on my system... so there goes the theory about #4...   grepped on bash
bash      22359             user    0u      CHR             136,12        0t0         15 /dev/pts/12
bash      22359             user    1u      CHR             136,12        0t0         15 /dev/pts/12
bash      22359             user    2u      CHR             136,12        0t0         15 /dev/pts/12
bash      22359             user  255u      CHR             136,12        0t0         15 /dev/pts/12
bash      18669             user    0u      CHR              136,9        0t0         12 /dev/pts/9
bash      18669             user    1u      CHR              136,9        0t0         12 /dev/pts/9
bash      18669             user    2u      CHR              136,9        0t0         12 /dev/pts/9
bash      18669             user  255u      CHR              136,9        0t0         12 /dev/pts/9

or this one grepped on /dev/ptr/4
lsof      12014             root    0u      CHR              136,4        0t0          7 /dev/pts/4
lsof      12014             root    2u      CHR              136,4        0t0          7 /dev/pts/4
grep      12015             root    1u      CHR              136,4        0t0          7 /dev/pts/4
grep      12015             root    2u      CHR              136,4        0t0          7 /dev/pts/4
konsole   18490             user   22u      CHR              136,4        0t0          7 /dev/pts/4
QXcbEvent 18490 18508       user   22u      CHR              136,4        0t0          7 /dev/pts/4
QDBusConn 18490 18542       user   22u      CHR              136,4        0t0          7 /dev/pts/4
radeon_cs 18490 18565       user   22u      CHR              136,4        0t0          7 /dev/pts/4
disk_cach 18490 18566       user   22u      CHR              136,4        0t0          7 /dev/pts/4
si_shader 18490 18567       user   22u      CHR              136,4        0t0          7 /dev/pts/4
si_shader 18490 18568       user   22u      CHR              136,4        0t0          7 /dev/pts/4
si_shader 18490 18569       user   22u      CHR              136,4        0t0          7 /dev/pts/4
si_shader 18490 18570       user   22u      CHR              136,4        0t0          7 /dev/pts/4
si_shader 18490 18571       user   22u      CHR              136,4        0t0          7 /dev/pts/4
bash      18632             user    0u      CHR              136,4        0t0          7 /dev/pts/4
bash      18632             user    1u      CHR              136,4        0t0          7 /dev/pts/4
bash      18632             user    2u      CHR              136,4        0t0          7 /dev/pts/4
bash      18632             user  255u      CHR              136,4        0t0          7 /dev/pts/4
sudo      20077             root    0u      CHR              136,4        0t0          7 /dev/pts/4
sudo      20077             root    1u      CHR              136,4        0t0          7 /dev/pts/4
sudo      20077             root    2u      CHR              136,4        0t0          7 /dev/pts/4
bash      20078             root    0u      CHR              136,4        0t0          7 /dev/pts/4
bash      20078             root    1u      CHR              136,4        0t0          7 /dev/pts/4
bash      20078             root    2u      CHR              136,4        0t0          7 /dev/pts/4
bash      20078             root  255u      CHR              136,4        0t0          7 /dev/pts/4

The 7 & 15 is the INODE (node) number on disk:
# ls -lai /dev/pts/4  /dev/pts/12
7 crw------- 1 user tty 136, 4  2 okt 00:23 /dev/pts/4
15 crw------- 1 user tty 136, 12  1 okt 21:45 /dev/pts/12


Also for free the lsof | grep command used this virtual tty "winfow"  the lsof stdout and grep stdin are missing because the were inter linked through an anonymous pipe.
Also considder that lsof collects a lot of info from various sources just to make a handy table to show.

Author

Commented:
Again you don't have to explain lsof command ;). But the theory about #4 doesn't go. Because you're saying this, I see that you actually don't understand it. My question is about the "open file table". And how the "open file table" looks like for stdin, stdout, stderr (default, terminal).

In your case, there are two entries in the "open file table":

/dev/pts/12
/dev/pts/9

Both can have a reference count of 4 each. Apparently you don't realize this, otherwise you would not say:

so there goes the theory about #4

These are the really basics of this subject and it's also pretty logical. Imagine two people connecting to the same server with for example Putty. Let's say they are typing "hi" exactly at the same time. If the fd's (0,1,2,255 of /dev/pts/12 and 0,1,2,255 of  /dev/pts/9)  would refer same entry in the open file table, then you would have a problem. One stream would overwrite the other stream. And that's also the reason why the theory of #4 still makes sense (2 entries in the open file table, both with count 4).

Anyway thanks for your help and I appriciate that you wanted to help, but I see that you're not the right person to answer my question. I don't mean it bad or something, but the I the answer can just look like this:

_ | offset | reference count | permissions | flags | pointers
_ |    ?   |        ?        |      ?      |   ?
possible more rows

Open in new window

nociSoftware Engineer
Distinguished Expert 2018

Commented:
Here are the tables Like i said before start HERE::::

/usr/src/linux/include/linux/fdtable.h for fdtable
struct fdtable {
        unsigned int max_fds;
        struct file __rcu **fd;      /* current fd array */
        unsigned long *close_on_exec;
        unsigned long *open_fds;
        unsigned long *full_fds_bits;
        struct rcu_head rcu;
};

/*
 * Open file table structure
 */
struct files_struct {
  /*
   * read mostly part
   */
        atomic_t count;
        bool resize_in_progress;
        wait_queue_head_t resize_wait;

        struct fdtable __rcu *fdt;
        struct fdtable fdtab;
  /*
   * written part on a separate cache line in SMP
   */
        spinlock_t file_lock ____cacheline_aligned_in_smp;
        unsigned int next_fd;
        unsigned long close_on_exec_init[1];
        unsigned long open_fds_init[1];
        unsigned long full_fds_bits_init[1];
        struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};

-------  which all reference the next structure
/usr/src/linux/include/linux/file.h    for the struct file
struct file {
        union {
                struct llist_node       fu_llist;
                struct rcu_head         fu_rcuhead;
        } f_u;
        struct path             f_path;
        struct inode            *f_inode;       /* cached value */
        const struct file_operations    *f_op;

        /*
         * Protects f_ep_links, f_flags.
         * Must not be taken from IRQ context.
         */
        spinlock_t              f_lock;
        enum rw_hint            f_write_hint;
        atomic_long_t           f_count;
        unsigned int            f_flags;
        fmode_t                 f_mode;
        struct mutex            f_pos_lock;
        loff_t                  f_pos;
        struct fown_struct      f_owner;
        const struct cred       *f_cred;
        struct file_ra_state    f_ra;

        u64                     f_version;
#ifdef CONFIG_SECURITY
        void                    *f_security;
#endif
        /* needed for tty driver, and maybe others */
        void                    *private_data;

#ifdef CONFIG_EPOLL
        /* Used by fs/eventpoll.c to link all the hooks to this file */
        struct list_head        f_ep_links;
        struct list_head        f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
        struct address_space    *f_mapping;
        errseq_t                f_wb_err;
} __randomize_layout
  __attribute__((aligned(4)));  /* lest something weird decides that 2 is OK */

For stding, stdout, stderr the various bit are filled on from the actual device in use, buffers being mapped, lock being claimed, etc. etc.  various fields for memory handling (rcu).

Author

Commented:
My question is not about the structures. And my question is about the default/terminal, so there are for example no locks being claimed yet et cetera. So again I'm asking for:

_ | offset | reference count | permissions | flags | pointers
_ |    ?   |        ?        |      ?      |   ?
possible more rows

Open in new window


But probably someone else understands what I mean and can answer the question in a different way, so it's useful for me.



.
nociSoftware Engineer
Distinguished Expert 2018

Commented:
I will refrain from continuing on this circular issue.

Author

Commented:
I think that's better indeed ;), but thanks anyway for your help and energy you put into it. I appriciated it!

Author

Commented:
@Noci: Sorry I'm bothering you again, but I'm reading everything again. Maybe I've missed something or I didn't understand something. You started with:

This table holds pointer to a central file table in the OS...
the fd[0] , fd[1] & fd[2] should all point to the same central entry

So by default stdin, stdout, stderror should refer to the same entry in the "open file table" (terminal). This does make sence to me. However, I was just reading this:

https://www.usna.edu/Users/cs/aviv/classes/ic221/s16/lec/21/lec.html#orgheadline6

This is about the default file descriptors in combination with the terminal (see figure 5). But they are showing two different entries in the open file table, and two different entries in the inode-table. In the end they both refer to tty. This figure is specifically about the default fd's in combination with a terminal.

So this is in contrast with one entry in the open file table for fd 0, 1, 2 (all to terminal). Everytime I'm reading different stuff about the same subject. If you're trying to learn it, it's pretty confusing.

So is that website wrong? Or is it different then you were saying?

Author

Commented:
And I just found a document that again says something else.

See: https://www.enseignement.polytechnique.fr/informatique/INF422/INF422_8.pdf#page=160 (page 160, example of no redirection)

In this case, fd 0 and fd 1/2 do not refer to the same entry in the open file table. Unlike my previous example (usna.edu), now suddenly they are refering to the same entry in the inode-table. So that's what my question is also about. Is there one entry in the open file table? Or are there 2 or 3 entries in the open file table (for the default terminal file descriptors)?

I think this is a pretty basic question. It surprises me why many people are wrong about this ... in the end only 1 of them is right. The problem is that I don't know anymore what the correct answer should be.

But if you see "0u, 1u, 2u" then probably it's about 1 entry in the open file table. Otherwise they would not have read/write (u). Then probably fd 0 would be read (r) and the other two (1,2) would be write (w). That's also what Noci said and that does make sense to me.

P.S. I'll make a new post for this, to keep it a bit more clear. I notice that I have to split my question in different sub-questions. For this one, see:
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#questionAdd

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial