What's The Meaning of 'C' in Result of Command "Ls -L /Dev/Tty'

what's the meaning of 'c' in result of command ls -l /dev/tty'?

It's a character-based (as opposed to block-based) device file.

Blocked-based devices are anything where it makes sense to transfer data in (surprisingly enough) blocks. By that, I mean things like disks.

Character-based devices (and again, this should come as no surprise) tend to transfer characters at a time. Things like terminals, serial ports, printers and so on.

If you're running a decent Linux distro, that information (plus more than you could probably ever need) can be obtained with the command:

info ls

which contains this little snippet:



The file type is one of the following characters:
- regular file
b block special file
c character special file
C high performance ("contiguous data") file
d directory
D door (Solaris 2.5 and up)
l symbolic link
M off-line ("migrated") file (Cray DMF)
n network special file (HP-UX)
p FIFO (named pipe)
P port (Solaris 10 and up)
s socket
? some other file type

What is special about /dev/tty?

The 'c' means it's a character device. tty is a special file representing the 'controlling terminal' for the current process.

Character Devices

Unix supports 'device files', which aren't really files at all, but file-like access points to hardware devices.
A 'character' device is one which is interfaced byte-by-byte (as opposed to buffered IO).

TTY

/dev/tty is a special file, representing the terminal for the current process. So, when you echo 1 > /dev/tty, your message ('1') will appear on your screen. Likewise, when you cat /dev/tty, your subsequent input gets duplicated (until you press Ctrl-C).

/dev/tty doesn't 'contain' anything as such, but you can read from it and write to it (for what it's worth). I can't think of a good use for it, but there are similar files which are very useful for simple IO operations (e.g. /dev/ttyS0 is normally your serial port)

This quote is from http://tldp.org/HOWTO/Text-Terminal-HOWTO-7.html#ss7.3 :

/dev/tty stands for the controlling terminal (if any) for the current
process. To find out which tty's are attached to which processes use
the "ps -a" command at the shell prompt (command line). Look at the
"tty" column. For the shell process you're in, /dev/tty is the
terminal you are now using. Type "tty" at the shell prompt to see what
it is (see manual pg. tty(1)). /dev/tty is something like a link to
the actually terminal device name with some additional features for
C-programmers: see the manual page tty(4).

Here is the man page: http://linux.die.net/man/4/tty

What does 2&1 mean?

File descriptor 1 is the standard output (stdout).

File descriptor 2 is the standard error (stderr).

At first, 2>1 may look like a good way to redirect stderr to stdout. However, it will actually be interpreted as "redirect stderr to a file named 1".

& indicates that what follows and precedes is a file descriptor, and not a filename. Thus, we use 2>&1. Consider >& to be a redirect merger operator.

major() and minor() give different numbers from ls

st_dev is the ID of device containing file, according to the man page. In other words, the device where the file's name resides. So it's the same as for your /dev directory, as you'll see if you use the stat command from your shell.

You're interested in st_rdev, which is Device ID (if special file) (again, from the man page).

The stat command shows both:

stat /dev/tty /dev/tty1


File: /dev/tty
Size: 0 Blocks: 0 IO Block: 4096 character special file
Device: 6h/6d Inode: 1035 Links: 1 Device type: 5,0
Access: (0620/crw--w----) Uid: ( 0/ root) Gid: ( 5/ tty)

....


File: /dev/tty1
Size: 0 Blocks: 0 IO Block: 4096 character special file
Device: 6h/6d Inode: 1044 Links: 1 Device type: 4,1
Access: (0620/crw--w----) Uid: ( 0/ root) Gid: ( 5/ tty)


Fixed code

#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>

int get_char_device(const char *name,
unsigned *dev_major, unsigned *dev_minor)
{
struct stat buf;
if (stat(name, &buf)) {
perror(name);
return 1;
}
if (!S_ISCHR(buf.st_mode)) {
fprintf(stderr, "%s: not a char device\n", name);
return 1;
}
*dev_major = major(buf.st_rdev);
*dev_minor = minor(buf.st_rdev);
return 0;
}

int main(void)
{
unsigned int major1, minor1, major2, minor2;
if (get_char_device("/dev/tty1", &major1, &minor1) ||
get_char_device("/dev/tty2", &major2, &minor2)) {
return 1;
}

printf("%d %d\n%d %d\n", major1, major2, minor1, minor2);
if (major1 == major2 && minor1 == minor2) {
puts("the two device files are equal");
return 1;
}
}

Not solved yet How can I run a program on a tty?

Try passing sh -c to your command:

$ setsid sh -c 'exec ls <> /dev/tty2 >&0 2>&1'

Mapping 2 USB devices to defined path

Instead of using /dev/ttyACM*, use the symbolic links that the kernel creates for you in /dev/serial/by-id.

Count only visible files in directory

Ignore the names that start with . by saying:

find . ! -name '.*' -type f | wc -l

From the man page:

! expression

 -not expression
This is the unary NOT operator. It evaluates to true if the
expression is false.

If you have filenames with newlines, then you can do using gnu find (as suggested by gniourf gniourf in comments):

find . ! -name '.*' -type f -maxdepth 1 -printf 'x' | wc -c

print all terminals of a user except current

find /dev/pts -mindepth 1 -maxdepth 1 \
-type c \
-user "$USER" \
! -path "$(tty)" \
-print

That is to say, we're finding:

  • Direct children of /dev/pts
  • ...which are character devices (like all PTYs should be)...
  • ...and which are owned by the current user...
  • ...and which are not the current tty.


Related Topics



Leave a reply



Submit