What is the purpose of "/dev/tty" when using the less command?

First I create a regular file with some contents (manual page of find command):

man find > test.txt

Open in new window


Then I use the less command to display some of these contents:

less test.txt

Open in new window


Now I press CTRL-Z to suspend the process. The process is still open, so now I can execute this command:

lsof | grep 'less'

Open in new window


By doing this, I get an idea which files are open with respect to the less-process. My result:

COMMAND  PID    USER  FD   TYPE  DEVICE  SIZE/OFF  NODE       NAME
less     24565  root  cwd  DIR   0,38    4096      21473055   /
less     24565  root  rtd  DIR   0,38    4096      21473055   /
less     24565  root  txt  REG   0,38    149944    22143102   /usr/bin/less
less     24565  root  mem  REG   9,1               22143102   /usr/bin/less (path dev=0,38)
less     24565  root  mem  REG   9,1               22135172   /usr/lib/locale/locale-archive-rpm (path dev=0,38)
less     24565  root  mem  REG   9,1               21741879   /lib64/libc-2.12.so (path dev=0,38)
less     24565  root  mem  REG   9,1               22265955   /usr/local/lib/libpcre.so.0.0.1 (path dev=0,38)
less     24565  root  mem  REG   9,1               21741743   /lib64/libtinfo.so.5.7 (path dev=0,38)
less     24565  root  mem  REG   9,1               21741946   /lib64/ld-2.12.so (path dev=0,38)
less     24565  root  0u   CHR   136,1   0t0       4          /dev/pts/1
less     24565  root  1u   CHR   136,1   0t0       4          /dev/pts/1
less     24565  root  2u   CHR   136,1   0t0       4          /dev/pts/1
less     24565  root  3r   CHR   5,0     0t0       207524942  [b]/dev/tty[/b]
less     24565  root  4r   REG   0,38    82765     25520978   /test.txt

Open in new window


The "/dev/tty" is the "controlling terminal" for the current process. The child process (less) inherits the terminal of the parent process (bash). Then why they are not just showing "/dev/pts/1" in this case (instead of "/dev/tty")?
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.

nociSoftware EngineerCommented:
Less opens it's own connection to the terminal for paging.
(think of the use case:
ls -l | less

Then the stdin is gone to a pipe. So for paging it needs access to the controlling tty hence it opens /dev/tty.
0
Maarten BruinsAuthor Commented:
But:

/dev/tty = controlling terminal current process

But that's /dev/pts/1 too, right? So what would be the difference between:

less     24565  root  3r   CHR   5,0     0t0       207524942  /dev/tty

Open in new window


and:

less     24565  root  3r   CHR   5,0     0t0       207524942  /dev/pts/1

Open in new window


I don't see the difference? That's basically what my question is about.
0
nociSoftware EngineerCommented:
When i write a program that cannot depend on  stdin to point to the controlling terminal, on can find it out by hacking though the kernel to find the controlling terminal (it is in the process table).  etc.etc.  
It is just that the device /dev/tty is created specific for this purpose, be able to contact to controlling terminal without knowledge of internal (subject to change) kernel structures. Now the kernel neatly resolves this for you...
Simple clean effective.
0
Determine the Perfect Price for Your IT Services

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

Maarten BruinsAuthor Commented:
Thanks!! That's useful! I think that's the answer.

To be sure, in css you have for example:

div {
    color: inherit;
}

Open in new window


I can compare it with that, right? If the color of the parent would be "black", I could also write:

div {
    color: black;
}

Open in new window


But this is not really handy, because if the parent element changes its color to yellow, then I want my div also to be yellow, but it's still black.

So because the "terminal-file" of the parent process might change, they are using something like "/dev/tty"?
0
nociSoftware EngineerCommented:
Because of the stdin of a process being variable (depending on redirection) the path to the controlling terminal is /dev/tty so i can always get the right one (for printing a prompt and reading an answer).

Only Daemon processes don;t have a controlling terminal, there the opening of /dev/tty will fail.

See also man 4 tty
0
Maarten BruinsAuthor Commented:
Thanks a lot noci! Probably it's the right answer and you're right about it all, but sorry I don't see it yet. In my example, it's about the less command. Maybe first I have to understand what exactly is happening and especially when it's about:

0u   /dev/pts/1
1u   /dev/pts/1
2u   /dev/pts/1
3r   /dev/tty
4r   /test.txt

Let's say we have:

less file.txt

Open in new window


Correct me if I'm wrong, but now "less test.txt" or "file.txt" is the standard input (fd 0) of the program (what has been entered on the keyboard). Now the program reads the contents of test.txt (fd 4). Now a part of these contents will go to the monitor via fd 1 (/dev/pts/1). Now you can press for example the d-key on the keyboard. Now some other/more contents of the file will be shown via fd 1 (standard output, /dev/pts/1).

Probably "3r   /dev/tty" is there to see/read the d-key on the keyboard in the example above? But if /dev/tty is basically /dev/pts/1, then why you in the first place you need "3r   /dev/tty", because it can go via "0u   /dev/pts/1" (standard input)?

Maybe with this example you can say what's wrong/correct about it, because then maybe I'll see what you mean.
0
nociSoftware EngineerCommented:
try lsof  -n | grep less | less
that should something along:

less      22273             user  cwd       DIR              253,5      4096     524890 /home/nico
less      22273             user  rtd       DIR              253,1      4096          2 /
less      22273             user  txt       REG              253,1    167880    2231684 /usr/bin/less
less      22273             user  mem       REG              253,1   2306832    2228609 /usr/lib64/locale/locale-archive
less      22273             user  mem       REG              253,1    145592     270696 /lib64/libpthread-2.26.so
less      22273             user  mem       REG              253,1   1840896     270699 /lib64/libc-2.26.so
less      22273             user  mem       REG              253,1    460912     282995 /lib64/libpcre.so.1.2.9
less      22273             user  mem       REG              253,1    448792     286293 /lib64/libncursesw.so.6.1
less      22273             user  mem       REG              253,1    157112     270683 /lib64/ld-2.26.so
less      22273             user    0r     FIFO               0,10       0t0  170451551 pipe
less      22273             user    1u      CHR              136,0       0t0          3 /dev/pts/0
less      22273             user    2u      CHR              136,0       0t0          3 /dev/pts/0
less      22273             usrr    3r      CHR                5,0       0t0       3085 /dev/tty

Open in new window


Where you can see that fd=0 reads a pipe.
in that case stdin cannot be used.
Less is a fairly simple tool, it doesn't attempt to verify if the stdin is a file, pipe or device or whatever...
For interaction with the user it just opens  /dev/tty (which is created for such purposes).

Less will open arguments on the command line on their own fd . =4 (next free).
Sources for less: http://www.greenwoodsoftware.com/less/download.html
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:
Nice one noci! Thanks a lot! Now I also understand your previous post:


Less opens it's own connection to the terminal for paging.
(think of the use case:
ls -l | less

Then the stdin is gone to a pipe. So for paging it needs access to the controlling tty hence it opens /dev/tty.

Actually now you're saying the same, but this time I understand it. I just needed some smaller steps to see it, because I'm pretty new to this all. But this is a good one to realize ... and to be aware of the possibility.
0
Maarten BruinsAuthor Commented:
Now I remember why I didn't understand it in the first place. On the internet I was reading this:

The "/dev/tty" is the "controlling terminal" for the current process.

But I saw it (incorrectly) as the file where for example fd 1 was pointing to (/dev/pts/1). So I thought, if there would be for example a pipe, then "/dev/tty" changes too. But it's about the controlling TERMINAL and not the file where for example fd 0,1,2 is pointing to. You could redirect all these fd's, but the controlling TERMINAL stays the same. But now it's anyway clear what exactly is meant.
0
Maarten BruinsAuthor Commented:
Sorry, but I thought about it some more and it still doesn't make sence to me. Let's say there is a pipe, so:

fd 1 other command -> pipe -> fd 0 less command

Open in new window


Now fd 0 can not be used to detect keystrokes. That's the reason why we need another file descriptor (in this case 3). But we can just have:

FD 3, READ, /dev/pts/1

In other words:

/dev/pts/1 -> fd 3

Open in new window


Then we still don't need "/dev/tty". So noci, I think it's not the correct answer to my question. If I would ask why a third file descriptor is used, then it would be the correct answer, but my question is why "/dev/tty" is used and not "/dev/pts/1".
0
nociSoftware EngineerCommented:
The file that is opened is /dev/tty, when opening  /dev/tty the controlling terminal is looked up in the ProcessHeader (in kernel structure) and the IO is then sent to THAT terminal. then name YOU provided as the access path is kept in the kernel for future reference.
(Earlier unix systems didn't even to bother to remember the name.... due to memory constraints).

You CAN find out by rummaging through the processheader (but location in the process header varies by version of the  OS) so you would need at least a dozen ways to find out (through /dev/mem and /dev/kmem) where the data is (processheaders, your processheader and then in that header where the controlling terminal is stored and how...).
You may expect /dev/mem and /dev/kmem to not exist due to security concernes.

note: /dev/tty is opened by less, not the shell.... so when stdin is redirected  it will point to a file....
the shell provides a means to redirect stdin, stdout, stderr... so any assumption of where they point are useless.
unless that assumption is resp. the place where to read input, the place where to send output and the place where to send error messages.
So the question you have to ask while writing a program how am i 100% sure i have the controlling terminal....

If you need you controlling terminal /dev/tty is the place to go.
(Unless you have kernel mode access (ie. are in a driver module for this kernel) and KNOW for the os at hand where to look).

/dev/tty is an extension to an internal interface meant to associate some OS events to terminals and if a device driver gets a signal to find the process using that device as controlling terminal. This isn't a common use now, but when modems were used in the past this was the most common use-case.

Now it's not about how you or i think how it works, but how the designers built the system in the 1970's and those methods are used since then and are still valid. stdin, stderr, stdout   controlling terminal are all part of set of agreements how to do IO on Unix.
These agreements are partly put in place in the OS (which actually doesn't care which fd is used for what purpose) the c-runtime library (libc) which implements IO calls. And the shell which provides the stdin/stdout/stderr concept. Then all programs that adhere to this concept.
Most programs do, but there are some that don't (best example some of the qmail control software).

Also daemons / service processes have their own concept and go to great length to reassign stdin/stdout/stderr to /dev/null  and even to disassociate themselves from the controlling terminal. (also using /dev/tty)  so a ^C, ^\ etc. typed on a terminal won't kill them.
0
Maarten BruinsAuthor Commented:
Firstable, thanks! That's a lot of information, but first I need the answer to my question to understand the rest what you're telling me. I'm trying to filter out the answer, but I don't see one (maybe that's my bad, because it's not clear for me at this moment). You're starting with:

The file that is opened is /dev/tty, when opening  /dev/tty the controlling terminal is looked up in the ProcessHeader (in kernel structure) and the IO is then sent to THAT terminal. then name YOU provided as the access path is kept in the kernel for future reference.
(Earlier unix systems didn't even to bother to remember the name.... due to memory constraints).

But this is already about "/dev/tty" ... my question comes down to: why you need "/dev/tty" in the first place, so why we can not use "/dev/pts/1" instead? So we don't even need to talk about "/dev/tty", because I just want to know why "/dev/pts/1" can not be used?

Let's say I'm writing a program (less command). Then I don't know if the terminal is "/dev/pts/1" or something else. So I can not write a script that opens a new file descriptor (3 in this case) that points to "/dev/pts/1". But if every system just uses "/dev/tty" as current terminal, then I can write a script that opens a new file descriptor that reads from "/dev/tty".

So this has nothing to do with pipes et cetera. Is this not just the answer?
0
nociSoftware EngineerCommented:
Ok how would the process know that /dev/pts/1 is the controlling terminal, and not f.e. /dev/pts/2, /dev/vc/5, /dev/tty10, /dev/ttyS0 or /dev/ttyUSB1 etc.

It isn't that /dev/pts/1 is the only device that can act as a terminal.... it just happens to be the first available when you opened a shell window.

Try logging in from another console, and open several other terminal windows and test with lsof in each of them. You will see other devices as stdin/stdout/stderr or controlling terminal.
The canonical name is /dev/tty.

So indeed your program would have a hard time to find out what the controlling terminal is.... unless /dev/tty is used.
Now if stdin allways would point to the keyboard there is no need for /dev/tty...., here is the catch there is no guarantee that stdin is pointing to the keyboard.

just for fun try:    ls -l | less >t.t
You will see all input is written to t.t without prompting....
That tells you less always writes to stdout, and only uses /dev/tty for the continue response.
(actualy it will ask for the size of the stdout and get invalid ioctl back (for TCGETS) and then decide it will behave like cat).
try:  ls -l | strace less >t.t
Which will show ALL calls being done from end of strace until exit.

Also you don't get a choice of where to open a file, it will be opened in the next slot.
If you follow the strace output then you can see it actualy opens the FD=3 a few times.

TCGETS more less is the binary version of stty -a
0
Maarten BruinsAuthor Commented:
A whole story again ... most of it I already know, but it's irrelevant to the question:

- I know the first available fd is used, but it's irrelevant.
- I know that not only "/dev/pts/1" can act as terminal. I just said:

Then I don't know if the terminal is "/dev/pts/1" or something else.

Did you anyway read/understand my post?

Let's say I'm writing a program (less command). Then I don't know if the terminal is "/dev/pts/1" or something else. So I can not write a script that opens a new file descriptor (3 in this case) that points to "/dev/pts/1". But if every system just uses "/dev/tty" as current terminal, then I can write a script that opens a new file descriptor that reads from "/dev/tty".

So this has nothing to do with pipes et cetera. Is this not just the answer?

I think I'm saying exactly the same as you are trying to say, so if you would understand my post, then you could just reply with: "yes, that's the answer". Or otherwise, what's wrong about the quote above?

But anyway I don't understand how you can say this:

Now if stdin allways would point to the keyboard there is no need for /dev/tty

If I have two terminal-windows open, then there are two different sessions with two "different" keyboards. In both cases, stdin points to the keyboard. But one is for example "/dev/pts/1" and the other one for example "/dev/pts/2". Then you still need "/dev/tty", right?

And anyway the pipe-story has nothing to do with the correct answer I think? It only explains to use an extra file descriptor, but it doesn't say anything about why to use "/dev/tty" instead of "/dev/pts/2".
0
nociSoftware EngineerCommented:
yes in both sessions.
And the pipe part is to illustrate that stdin isn't always a keyboard.

Just to be clear there is NO direct connection between /dev/tty and /dev/pts/X or /dev/ttyX.
The /dev/pts/X is always a pair of devices named master & slave. The slave is in the shell program, the master is in the X-windows program (xterm, konsole, etc. etc. ) and they work like a bidirectional pipe. (man 4 pts)
the actual keyboard (/dev/ttyX  or /dev/vc/X [ the current console ] )  is bound to the X- or Wayland display server.

If running on a bare non graphic console (Ctrl-Alt-F1 or Ctrl-Alt-F2.. ) /dev/ttyX or /dev/vc/X (depends on distro) would be seen as the controlling terminal.
less would still use /dev/tty to communicate with those.

the implementation of  Character device 5,0 (/dev/tty) is in  /usr/src/linux/drivers/tty/tty_io.c   search for: MKDEV(TTYAUX_MAJOR, 0) in the function: tty_open_current_tty()
which call get_current_tty() which calls tty_kref_get() to return either NULL or the pointer to the internal description of the current controlling terminal.
0
Maarten BruinsAuthor Commented:
But before you will put more information in this topic, first let's get the basics clear. I'll do it step by step otherwise it's not clear to me what part you're talking about. Let's start with the first step. First you said:

Now if stdin allways would point to the keyboard there is no need for /dev/tty

Is it correct that this is actually incorrect of you? Stdin can always point to a keyboard (e.g. /dev/pts/1, or /dev/pts/2, et cetera) but then you still need /dev/tty, because you don't know whether it's e.g. /dev/pts/1 or /dev/pts/2.

So first let's only discuss this specific part without putting too much irrelevant (to this specific part) other information to it.
0
nociSoftware EngineerCommented:
If stdin would ALWAYS be the keyboard (by definition) i can always read stdin if i want a response from the user.
So /dev/tty is a fix for reaching out to the keyboard when stdin is NOT the keyboard.
0
Maarten BruinsAuthor Commented:
Ah then I totally don't understand it yet ;). Let's go on on this track, because first I need to understand this before I am able to understand the other information. First you said:

Ok how would the process know that /dev/pts/1 is the controlling terminal, and not f.e. /dev/pts/2

You can have 1 keyboard, but two open terminal-windows, so then we will have "/dev/pts/1" and "/dev/pts/2". Imagine such a case (where stdin is always the keyboard). Why in this specific situation we don't need "/dev/tty"? How the program knows whether /dev/pts/1 or whether /dev/pts/2 is the controlling terminal?  I would expect "/dev/tty" is needed for that (although stdin is for /dev/pts/1 and /dev/pts/2 the keyboard)?
0
nociSoftware EngineerCommented:
In the processheader (in-kernel bookkeeping of a process there is a structure that deals with signals, in that structure there is a reference to the controlling terminal which ever it is.   Jobctrol is delivered through signals ( CTRL/C, CTRL/\ CTRL/Z etc., SIGHUP, SIGINT, SIGSTOP, etc. )) A terminal driver that receives this needs to post those signal to all or header process(es) that have this terminal as Controlling Terminal
Thats why it is stored there.

If user input allway comes from stdin then there is by definition no need for /dev/tty.   (/dev/tty is not an actual terminal, during the open it searches the kernel processheader for the current process, and check the reference for the controlling terminal:

From the tty_io.c header,  MKDEV(TTYAUX_MAJOR, 0)  = 5,0 aka /dev/tty.

/**
 *      tty_open_current_tty - get locked tty of current task
 *      @device: device number
 *      @filp: file pointer to tty
 *      @return: locked tty of the current task iff @device is /dev/tty
 *
 *      Performs a re-open of the current task's controlling tty.
 *
 *      We cannot return driver and index like for the other nodes because
 *      devpts will not work then. It expects inodes to be from devpts FS.
 */
static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
{
        struct tty_struct *tty;
        int retval;

        if (device != MKDEV(TTYAUX_MAJOR, 0))
                return NULL;

        tty = get_current_tty();
        if (!tty)
                return ERR_PTR(-ENXIO);

        filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
        /* noctty = 1; */
        tty_lock(tty);
        tty_kref_put(tty);      /* safe to drop the kref now */

        retval = tty_reopen(tty);
        if (retval < 0) {
                tty_unlock(tty);
                tty = ERR_PTR(retval);
        }
        return tty;
}

Open in new window


The code for other terminals (/dev/pts/X) use the internal reference for that terminal(  kref of (/dev/pts/X ) .

The controlling terminal is the device that the shell is handed when starting up, IF it is a real device then it will become the controlling terminal.
Anything starting from the "init" (pid=0) process will have the console as the controlling terminal.  [ definition, no choice here ].

So if a modem connection is started from /dev/ttyS10 then the controlling terminal will be /dev/ttyS10
(which is started from getty() with a command resembling: " /bin/sh  </dev/ttyS10 >/dev/ttyS10 2>/dev/ssh10"
If a windowed program (xterm) starts a shell with the slave /dev/pts/1 device as input that one will be the controlling terminal.
the command would look like:   "/bin/bash </dev/pts/1 >/dev/pts/1 2>/dev/pts1" for the first session and
"/bin/bash </dev/pts/2 >/dev/pts/2 2>/dev/pts2" for the 2nd session.
If xterm has the focus it will receive all X keyboard input and push that to it's running shell through the master of /dev/pts/1
if another xterm get the focus it will receive all X keyboard input instead and push that to /dev/pts/2
The X-keyboard is a "virtualised" keyboard that can receive input from many device amongst which is the real keyboard..(on the console) or a Virtual keyboard show on a touch screen (think Gboard on an android phone).

You cannot do /dev/pt/3 just by yourself, you first need to create a new terminal port.
if you want to experiment with this the TMux tool  is needed: https://tmux.github.io/

It can also be an attach phone keypad, or specialized devices like U2F usb sticks for passphrases etc. A remote control for a multimedia center.
0
Maarten BruinsAuthor Commented:
Soon I have to leave, so I didn't read your post completely yet, but I have two quotes from you:

Now if stdin allways would point to the keyboard there is no need for /dev/tty

and:

If user input allway comes from stdin then there is by definition no need for /dev/tty.

These are two different quotes, so which one is the correct one? Is it about the keyboard or is it about the stdin? Stdin can also be connected with a file, so according to your first quote then maybe you need /dev/tty, but according to the second post you don't need /dev/tty.
0
nociSoftware EngineerCommented:
they are the same/equivalent....    
1) IF stdin is a keyboard...... THEN then use stdin as the keyboard
2) IF stdin is a keyboard ..... THEN why build a mechanism to find a keyboard.....
Both express the " no need for /dev/tty"

But that is fiction, STDIN can be a file, pipe, tty, whatever...
==> inference:   /dev/tty is needed because stdin can be different from a keyboard.
0
Maarten BruinsAuthor Commented:
But keyboard? Did you read my post? You're saying:

If user input allway comes from stdin then there is by definition no need for /dev/tty.

A user can also give a file as input. This is what I said:

Stdin can also be connected with a file

So I don't understand why you're only talking about the keyboard?
0
nociSoftware EngineerCommented:
The necesity of USER input (aka not a file, pipe, ... but actual keys typed, f.e with a password/passphrase, or when a pager is used like less)
then you need access to a keyboard..... /dev/tty is only meant to reach that keyboard [ if it exists ].

That a file can be user input and can be specified is not relevant for /dev/tty usage.  [ which was the topic of this Q..? ]

Let's rephrase:   if the "user input" (waiting for a keystroke like space.. / .. to show the next page of data) could come from a file what would the value of less ... you would get the same as the "cat" command unless the file didn't have enough characters or blank lines to show all input, after which it would hang or abort the showing of data.
That doesn't wait on a keystroke it just plain copies the stdin content to stdout.
0
Maarten BruinsAuthor Commented:
Thanks a lot noci! I still don't understand it, but now at least I know why I don't understand it, because I realize that I don't know what exactly a "controlling terminal" is. Probably if I know that, then it's more clear to me. Sorry for that, during asking the question I found out that I don't really understand the term "controlling terminal".

I just started to read about the controlling terminal. For example: https://unix.stackexchange.com/questions/404555/what-is-the-purpose-of-the-controlling-terminal

With controlling terminal, even if you already redirect stdin to other places/files, you still be able to read/write from/to controlling terminal, the /dev/tty.

Can I see "/dev/pts/1", "/dev/pts/2", et cetera as being a controlling terminal? That's what I was thinking, but probably that's incorrect because then the quote above doesn't make sense to me. If I redirect stdin to other places/files, then I can still read/write from/to for example "/dev/pts/1"? So then I still don't need "/dev/tty"? Let's say my bash process looks like this:

FD 0 -> redirection to non-terminal file
FD 1 -> redirection to non-terminal file
FD 2 -> redirection to non-terminal file

Then it's still possible to write to /dev/pts/1 I assume?

Furthermore I'm thinking this: let's say I do this:

cat

Open in new window


Now I'm connected to the "input stream". I can type something, press enter, and I'll see it immediately on my screen (so in the end I see everything two times). But what exactly is happening if I press CTRL-Z on my keyboard (Suspend Process) ... is "CTRL-Z" also going through the standard input (file descriptor 0) of the cat command? In other words, can I see /dev/pts/1 as a "keyboard-file"? Or is there "something" in between my keyboard and /dev/pts/1? (something that detects the control-key and decides to not send these keystrokes to the standard input of the cat command)
0
nociSoftware EngineerCommented:
The controlling terminals is decided by the process that starts another process.

During logons on the console:  agetty / mingetty / mgetty (or similarly)
During login from modems: mgetty.
During logon on windows --- nothing.... The XDisplay  manager will own the console it was started on.
 The windows manager (Gnome, KDE, LXD) talks to the Virtual Keyboard in XDisplayManager
   Konsole, xterm etc. will talk to the WindowManager (and receive the keystrokes when the have the focus).

*getty, Konsole, Xterm etc. will establish the controlling terminal for you using ioctl() with the options TIOCSCTTY  will that the device unit as a CTTY.

The controlling terminal can bee seen with ps axf ...
all programs that have a ? in 2nd column have NO controling tty, all the ones that have no ? there show a device name without /dev/
(so pts/1 or pts/2... )

Bare console:
You press CTRL/Z  (this will send the SIGSTOP to the currently running process (halting it), and SIGCHLD to the parent (the shell).
The process is found by search for all processes that have the TTY where the CTRL/Z as CTTY in their processheader.

Windows Konsole example:
You press CTRL/Z this will send the CTRL/Z to X-server (which is running the console in raw mode) this makes it a key symbol: VK_CTRL_Z and sends it tothe WindowManager which sends it to  Konsole (assuming  is has focus)  which will then  do the kill() with  send it to the master part of /dev/pts/X  the slave side will (if in cooked mode) interpret the CTRL/Z and handle the SIGSTOP/ etc.

If a device is in raw mode then the character is passed on as is.
So there is quite a lot between the keyboard and /dev/pts/X on the slave side. (aka the shell you run in a window).

The common thing is the TTY driver (which is slightly different between real tty and virtual tty like /dev/pts/...)
0
Maarten BruinsAuthor Commented:
Okay, again let's try it step by step because everytime it's too much information while I don't even understand the first step. Try to react on what I'm saying, because what you're saying I don't understand. You're making too big steps.

Let's start with:

if I press CTRL-Z on my keyboard (Suspend Process) ... is "CTRL-Z" also going through the standard input (file descriptor 0) of the cat command?
0
nociSoftware EngineerCommented:
IF this is the REAL DEVICE (no windowing system used).
AND the REAL DEVICE is in RAW MODE
then YES

IF this is the REAL DEVICE (no windowing system used).
AND the REAL DEVICE is in COOKED MODE
then it will case the TERMINAL DRIVER to send a SIGSTOP to the "cat" process and SIGCHLD to the parent of the "cat" process.

When running windowing software the path is much longer See earlier answer.
0
Maarten BruinsAuthor Commented:
I'm already stuck after the first 6 words:

IF this is the REAL DEVICE

The question is about a keyboard. I think that's a real device, right? So probably you mean something else ... what do you mean by "if this is the real device"?
0
nociSoftware EngineerCommented:
keyboard is a read device, if it is connected to console #1 (CTRL-ALT-F1) it is called /dev/tty1, if connected to Console #2 ( CTRL-ALT-F2 )  it is called /dev/tty2  et. up to console #12. If it is the COM1 serial port the REAL DEVICE is /dev/ttyS0. If you plugin a USB Serial device it can be called /dev/ttyUSB0 (if it is the first on most adapter, but depending on USB device YMMV).    USB Keyboards are handles as a HID (Human Interaction Device and connect like a local keyboard).
0
Maarten BruinsAuthor Commented:
I think I'm gonna give up soon. My question was:

what do you mean by "if this is the real device"?

Again you're posting a lot but I don't see any answer to this question. My question was about a keyboard, so how you can say "if this is the real device". What do you mean?
0
nociSoftware EngineerCommented:
How can i explain this is from the view of a process...., and that the device can be /dev/tty1, or /dev/tty2, or /dev/ttyS0 or... (real devices other than memory involved)
but NOT /dev/pts/1 or /dev/pts/2 or /dev/null as the last 3 are examples of devices that only move some blocks around in memory, only memory involved..
0
Maarten BruinsAuthor Commented:
Ah, now you're saying something interesting. So a device can not be /dev/pts/1? That's new for me. Usually fd 0 is the standard input (keyboard). In my case, I see:

FD 0   <-   /dev/pts/1

To be sure, a keyboard can be seen as a device, right? Then why "/dev/pts/1" can not be seen as device/keyboard?

I've no idea what you're trying to explain with "if this is the real device". My question was about a keyboard, so I don't see how a keyboard can not be a real device. Or maybe you were refering to something else? But it was about my example, it was about a keyboard, so otherwise you must have refered to something else in my example, but I have no idea what. But for now, let's first get this clear:

To be sure, a keyboard can be seen as a device, right? Then why "/dev/pts/1" can not be seen as device/keyboard?
0
nociSoftware EngineerCommented:
Ok different route: keyboard is connected to the Keyboard serial port (small DIN plug) or USB port.
that port's input is sent to the CURRENT CONSOLE (/dev/tty1... /dev/tty12).  depending which one is chosen. (KBD driver, or USB HID driver, also for the mouse btw).
A program running on  those consoles can receive the data.   (Until here there are Physical devices involved).....
CTTY = Controlling Terminal

Terminal device (REAL or VIRTUAL) can be in two major modes:
- RAW: all data is passed on as is, the terminal driver does nothing more then receive and send data.
- COOKED: some data is filtered by the driver. CTRL/C is converted to signal SIGQUIT to All process that have this port are CTTY, CTRL/\ is converted to a SIGINT to the processes havint this as CTTY, CTRL/Z is send as two signals: 1) SIGSTOP to active process, 2) SIGCHLD to parent SIGCHLD signal a child process is being molested.

Is this clear as it is?   (Virtual devices in windowed systems can come later).
0
Maarten BruinsAuthor Commented:
Thanks! It's already late here, so I need to go to bed now, but tomorrow I'll dive further into it. I think the last post is useful to start with. I also found:

https://en.wikipedia.org/wiki/Pseudoterminal#/media/File:Termios-script-diagram.svg

I think that's about the same what you're trying to tell me. First I need to get the basics clear, so I have to read more about this. So I'll do my "homework" and then I'll come back to this topic. Anyway already for now thanks a lot for all the energy/time you've put into it. The last post is useful to me I see already.
0
nociSoftware EngineerCommented:
Looks like it.....
0
Maarten BruinsAuthor Commented:
Thanks to this question: https://www.experts-exchange.com/questions/29121496/What-the-purpose-of-dev-tty.html, now I can follow the posts here. You confused me a bit by posting too many details. Actually I already understood terms like "terminal" and "controlling terminal" the correct way. I will try to answer my own question now. You can let me know if it's correct.

The question was to explain:

less     24565  root  3r   CHR   5,0     0t0       207524942  /dev/tty

See: https://www.experts-exchange.com/questions/29121496/What-the-purpose-of-dev-tty.html

True, but how do you know that the terminal to read is /dev/pts/1 and not say, /dev/pts/5 or something. The FD 0 was redirected to the file by the shell before the program started to run, so how do you know which terminal to try and read from?

1. The first step to realize is:
If there wouldn't be "/dev/tty", then the only way (for a program) to find out what the terminal is (for input), is to look at fd 0 (standard input).
 (actually this is already the answer and from this point I understand it, but this was the catch for me)

2. The second step to realize is:
File descriptor 0 (standard input) doesn't need to be associated with a keyboard. This must only be the case when starting the program. Let me explain this a bit more. From the start of the program we have:

less     24565  root  3r   CHR   5,0     0t0       207524942  /dev/tty

If fd 0 would be "/dev/pts/1" at the beginning, we could also start with the one below, because "/dev/pts/1" is known:

less     24565  root  3r   CHR   5,0     0t0       207524942  /dev/pts/1

Then later on it's no problem to redirect file descriptors, because "/dev/pts/1" is already known. After the redirects, fd 0 doesn't have to be associated with the keyboard anymore.

3. The third step to realize is:
The less program can start with fd 0 (standard input) that is associated with e.g. a pipe instead of the keyboard. In such a case, the less command gets its standard input via the pipe instead of a keyboard. The only way to know that the terminal is "/dev/pts/1", is to look at fd 0. However now there is a problem because there is no "/dev/pts/1", there is a pipe instead. The "only" way to be aware of "/dev/pts/1" is to use "/dev/tty".

So that's why "/dev/tty" is used. Is this correct?
0
nociSoftware EngineerCommented:
Short NO:

1)   there is no causal connecyion between fd[0] and  /dev/tty ... a program allways has fd[0] (it might be closed but that is unlikely) and it may very well not have a CTTY (all server process have NO CTTY).

2) No the PARENT process setup the fd[0]... then erases it own user memory and replaces it with something else using the exec() call.
     the parent creates a child (perfect copy with exception of pid)  using fork() .  
    All unix systems use the fork()/exec() to start programs there is no other way). A child inherrits it's fd[0..limit] from it's parent. So fd's are already assign at start of program.

3) conflicts with your realisation #2...  if program strat with stdin = CTTY how would it known to switch to a pipe / file...
The last sentence is correct though.

I guess the misunderstanding is how DOS works vs. how UNIX works.
In MS-DOS all programs had to solve <, > etc. themselves.
In Unix the SHELL does all the heavy lifting...

if you type less <file   the program gets executed as:   (in the shell)
   fd=open("file",0);
   dup2(fd,0);
   close(fd);
   exec("/usr/bin/less", "less", 0)
and sees:
less # (argc=1, argv[0]="less", argv[1]=NULL ) no arguments...., with stdin preopened to file

if you type less file
the program is started as:
   execl("/usr/bin/less","less", "file",0)
Program sees:
less file #(argc=2, argv[0]="less", argv[1] = "file", argv[2]=NULL)
0
Maarten BruinsAuthor Commented:
Uhmz, yeah what you're saying does make sense. I just added a question for @mccarl here: https://www.experts-exchange.com/questions/29121496/What-the-purpose-of-dev-tty.html

I've also checked these differences:

less < test.txt
COMMAND     PID    USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
less      20976    root    0r      REG               0,38     82765   25520978 /test.txt
less      20976    root    1u      CHR              136,1       0t0          4 /dev/pts/1
less      20976    root    2u      CHR              136,1       0t0          4 /dev/pts/1
less      20976    root    3r      CHR                5,0       0t0  207524942 /dev/tty

Open in new window


less test.txt
COMMAND     PID    USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
less      20999    root    0u      CHR              136,1       0t0          4 /dev/pts/1
less      20999    root    1u      CHR              136,1       0t0          4 /dev/pts/1
less      20999    root    2u      CHR              136,1       0t0          4 /dev/pts/1
less      20999    root    3r      CHR                5,0       0t0  207524942 /dev/tty
less      20999    root    4r      REG               0,38     82765   25520978 /test.txt

Open in new window


cat test.txt | less
COMMAND     PID    USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
less      21083      root    0r     FIFO                0,8       0t0 2372368848 pipe
less      21083      root    1u      CHR              136,1       0t0          4 /dev/pts/1
less      21083      root    2u      CHR              136,1       0t0          4 /dev/pts/1
less      21083      root    3r      CHR                5,0       0t0  207524942 /dev/tty

Open in new window


This doesn't really answer my question, but anyway it's good to be aware of the differences. Now I know that my previous answer/shot is incorrect. However, I'm still struggling with why we need "/dev/tty". Let's say my shell is bash. I start with the bash-process:

FD 0 (standard input)    <- /dev/pts/1 (terminal-file/keyboard)
FD 1 (standard output)  -> /dev/pts/1 (terminal-file/keyboard)
FD 2 (standard error)    -> /dev/pts/1 (terminal-file/keyboard)

The less-program starts with a fork of this. Then less knows at this point that "/dev/pts/1" is the controlling terminal? So it doesn't have to use "/dev/tty". Maybe from this point of view you can make it more clear...or which mistake I'm making with thinking this.

Or do we you need "/dev/tty" if file descriptor 0 of the bash-process is redirected to a non-keyboard/non-terminal file? Then probably you don't start with "/dev/pts/1" as fd=0, so then the less-process has no idea about "/dev/pts/1".
0
Maarten BruinsAuthor Commented:
Okay see also: https://www.experts-exchange.com/questions/29121496/What-the-purpose-of-dev-tty.html

I think I'm just right. I said:

1. The first step to realize is:
If there wouldn't be "/dev/tty", then the only way (for a program) to find out what the terminal is (for input), is to look at fd 0 (standard input).
 (actually this is already the answer and from this point I understand it, but this was the catch for me)

You replied with:

there is no causal connecyion between fd[0] and  /dev/tty

I didn't say that there is a connection between fd[0] and /dev/tty. I'm only saying if fd 0 is associated with the terminal-file/keyboard (/dev/pts/1), then "/dev/tty" within that process actually also refers to "/dev/pts/1". So in such a case, "/dev/tty" would not be necessarily, because the program is aware of "/dev/pts/1" via fd=0?

Let's go to the second step. I said:

File descriptor 0 (standard input) doesn't need to be associated with a keyboard. This must only be the case when starting the program.

Okay now I know from @mccarl that this actually happens just before starting the program. However, this hasn't any influence on the answer about "/dev/tty". If the file descriptor (0) is associated with the keyboard, then the program is aware of "/dev/pts/1", without the need to use "/dev/tty". That's actually what I was saying. So apart from a small mistake about a detail, the principles were correct in my opinion.

The last step:

3. The third step to realize is:
The less program can start with fd 0 (standard input) that is associated with e.g. a pipe instead of the keyboard. In such a case, the less command gets its standard input via the pipe instead of a keyboard. The only way to know that the terminal is "/dev/pts/1", is to look at fd 0. However now there is a problem because there is no "/dev/pts/1", there is a pipe instead. The "only" way to be aware of "/dev/pts/1" is to use "/dev/tty".

Actually I don't see anything wrong about this? This is just the answer in my opinion. Let's say I have a bash process running:

FD 0 (standard input)   <- /dev/pts/1 (terminal-file/keyboard)
FD 1 (standard output)  -> /dev/pts/1 (terminal-file/keyboard)
FD 2 (standard error)   -> /dev/pts/1 (terminal-file/keyboard)

Now I do something like this:

echo 'bla' | less

This is what happens:
- Bash calls fork()
- Bash connects the output of the echo-command with the input (fd 0) of the just created stuff (fork).
- Now the less program starts. However, now the program doesn't know where to get the keyboard-input from.

Now "/dev/tty" is there to solve this problem. This is exactly what I was saying in the quote above. I really don't understand what is wrong about this? And I think @mccarl is saying the same here: https://www.experts-exchange.com/questions/29121496/What-the-purpose-of-dev-tty.html

About my third quote you said:

3) conflicts with your realisation #2...if program strat with stdin = CTTY how would it known to switch to a pipe / file

But my third quote was about a program starting with a pipe. So I have no idea why you changed this to CTTY instead of a pipe? Probably you were still talking about step 2!! ...about my mistake that I thought a program (fd 0) can start with CTTY and then later on become a pipe. However, this is just a small detail but this doesn't change the principles behind understanding "/dev/tty". I think I was already seeing it the correct way, only with a small mistake that was not that relevant for understanding "/dev/tty". Maybe your "3)" didn't refer to my "3", but then it's quite confusing to call this "3" too.
0
Maarten BruinsAuthor Commented:
Now I know (I think) the purpose behind "/dev/tty" and I'm reading back, I have to say that explaining things is not your best feature ;) (at least in this question). I see/notice that you know a lot and you're also sharing a lot of your knowledge, but sometimes too much information can distract from what the question actually is about. Actually mccarl made this entire topic clear to me in a couple of posts (https://www.experts-exchange.com/questions/29121496/What-the-purpose-of-dev-tty.html). I don't mean it bad or something and I'm really thankful for all your help (and the patience you have with me because I'm not the easist person when asking questions). Many things were also helpful, but I only wanted to say that sometimes too much information can work counter-productive.


An example:

2) No the PARENT process setup the fd[0]... then erases it own user memory and replaces it with something else using the exec() call.
     the parent creates a child (perfect copy with exception of pid)  using fork() .  
    All unix systems use the fork()/exec() to start programs there is no other way). A child inherrits it's fd[0..limit] from it's parent. So fd's are already assign at start of program.

Meanwhile I know what you were trying to say, but compare your quote with mccarl's quote. You both were trying to say about the same thing (correct me if I'm wrong).


No, it doesn't. The fork happens first, but then it is still bash code that is running in the child process. So then after the fork, bash sets up the redirection, and then it calls "exec" to load and run the less code.

This is so much clearer. Just normal/understandable terminology. I had even no idea on which part of my post you were responding. You could for example start with quoting this:


File descriptor 0 (standard input) doesn't need to be associated with a keyboard. This must only be the case when starting the program.

You could just say that if a program starts with a certain fd 0, that this doesn't change later on (to for example a pipe). If there is a pipe involved, it's "generated" before the program starts (but correct me if I'm wrong). Another example, this quote of mine:

3. The third step to realize is:
The less program can start with fd 0 (standard input) that is associated with e.g. a pipe instead of the keyboard.

You replied with:

3) conflicts with your realisation #2...  if program strat with stdin = CTTY how would it known to switch to a pipe / file...
The last sentence is correct though.

This doesn't conflict with #2, because now the program starts with a pipe, so that's what is happening in reality. Bash generates the pipe and then later on the program will be started. So if the program starts with a pipe, then it can not start with CTTY like you are saying:

if program strat with stdin = CTTY

I'm not saying that you don't know how it's working, because you know ... but some things can be easier said with less information. Anyway I'm thankful for your help and I'll give you all the "credits" for answering this question. I'll still let the question open, because for now I assume that my final conclusions are correct, but first this need to be confirmed by you. Maybe I'm still completely wrong about it and this entire post doesn't make sense ;).
0
nociSoftware EngineerCommented:
@0: Too much information cannot be helpful...
Your firsts questions were about kernel level operations.. (why parts of lsof are what they are...) and there was an interpretation of this... (it was incomplete at best, also no offence intended).   There fore the reference to the kernel etc.
So there was knowledge inferred which was not there....   One ges to kernel level when there is some basic understanding of the userland issues & features.
small advise: instead of trying to drill down first on details (like being opened for r/w/u.. maybe just accept that there are conventions that are mostly followed, and start questions from the top in stead of from the nitty gritty details. It gives a better chance to get the right answer the first time.
If there are questions about how a crankshaft bearing works (inside a motorbike's motor) then at least  it should be expected knowledge how a motorbike looks like and can be operated and used.
That's why i started a later on a comment with another with ok: different route.    Trying to establish a common ground.

@2: even the pipe is generated before the fork, because the pipe() call gives 2 fd's one for the left and one for the right part of the |.
After the fork() the "invalid" one is closed  and the "right" one set to the right fd in both children of the shell.

@3: was the right one, wording should be #2 conflict the #3 one, #3 is correct.

btw. there also is the option to request a delete of Q&A.
0
Maarten BruinsAuthor Commented:
small advise: instead of trying to drill down first on details (like being opened for r/w/u)

But first I always read the basic stuff about a subject, but then I usually have more questions about it. If I can not find the answer to those questions on the internet, I'm asking them here. By asking myself the question about "r/w/u", I've learned a lot of things that I wouldn't be aware of otherwise. So maybe learning like that (without details) works for you, but not for me. I need to ask myself questions, and I need to understand the details otherwise I'm learning without really understanding it.

And maybe you're not aware of it (because you have the knowledge in your head), but many websites on the internet contradict each other. For example with the "open file table", on different websites this term can refer to different things. Just by reading for example one book with the basics about it, you will not find out such things. I also noticed this when it's for example about pipes, redirects et cetera.

And that the pipe is generated before the fork is just how you look at it. If you see the pipe as the pipeline between the two fd's of two processes, then it's not created before the fork. But if you see the pipe as the system call pipe(), then it's indeed created before the fork. I am aware of that. So it's not that I don't have the knowledge, but sometimes you're saying things in a way that I start to doubt about the knowledge I have so far. This "pipe" is a good example, if I wouldn't understand a pipe 100% yet, then I would be confused now by what you were saying, while actually I have the right idea of a pipe in my head. Now instead, I can correct you by saying there are two ways to look at a "pipe" (system call / pipeline between two fd's of different processes).

And:

@3: was the right one, wording should be #2 conflict the #3 one, #3 is correct.

Ah, yeah things like that confused me. If you would have said this in the first place, then probably I was less confused. But anyway one more time, thanks a lot for all the help! In the end, we have an answer to my question.

btw. there also is the option to request a delete of Q&A.

For me it's not necessary. Maybe this thread can be useful for other people later on. If you want it to be deleted, just let me know.
0
nociSoftware EngineerCommented:
It can be useful... not for me to decide though..
pipeline processing is a bit more involved, please see the sources of bash i mentioned else where.
(typo's fixed).
0
Maarten BruinsAuthor Commented:
pipeline processing is a bit ore involved

Sorry, again I don't understand you. What are you trying to say? Is "ore" a typing mistake of it means something? (my English is not that good, so that doesn't help either)
0
nociSoftware EngineerCommented:
A pipe line is broken into so called "simple commands"    lets assume 3 commands in a Pipe:
COMMAND1 | COMMAND2 | COMMAND3

this makes the shell  create 2 pipe()'s  each having to fd's  (fdi for pipe  input, fdo for pipe output)  it becomes
create pipe1 (fdi1, fdo1)
create pipe2 (fdi2, fdo2) and setup for

COMMAND1 >fdi1 &
COMMAND2 <fdo1 >fdi2 &
COMMAND3 <fdo2 &

then execute these 3 simple commands and wait for all to complete.
retain the exit status of the last command as result.
0
Maarten BruinsAuthor Commented:
I still don't know what "ore" is? Ah, you just changed your post? Now I see "more". Did I quote you incorrectly or you have just changed your post? I've to go to bed now, but later on I'll press the buttons in this thread to mark the solution. So then you know that I will not forget about it.
0
nociSoftware EngineerCommented:
I fixed the post, (i also mentioned typo's fixed). Appearantly we can now update old posts. (that's relatively new.).
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.