Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1754967
  • 博文数量: 413
  • 博客积分: 8399
  • 博客等级: 中将
  • 技术积分: 4325
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-09 10:44
文章分类

全部博文(413)

文章存档

2015年(1)

2014年(18)

2013年(39)

2012年(163)

2011年(192)

分类: LINUX

2011-06-22 12:46:46

我们知道在Linux的/dev目录下有一些特殊的文件,比如:/dev/tty, /dev/tty0, /dev/tty1 ...还有/dev/pts/0, /dev/pts/1, /dev/pts/2 ... 等。对于它们我们一般感觉比较理解。本文从编程的角度对其进行一些分析。

首先我们搞清楚几个缩写:
tty是Teletype或者Teletypewriter的缩写。是早期的一种终端设备--电传打字机。通过串行线连接打印机键盘阅读和发送信息的东西,后来被键盘与显示器取代,所以现在一般叫做“终端”。

pty即Pseudo-TTY 伪终端或者叫做虚拟终端。是成对的逻辑终端设备(即master和slave设备, 对master的操作会反映到slave上)。

pts是Pseudo Terminal Slave的缩写。是pty的实现方法,与ptmx(pseudo-terminal master)配合使用实现pty。当我们telnet到主机,或者直接使用xterm,或者程序需要交互时,我们就需要一个终端。因为只有通过终端我们才能实现人与计算机的交互。只要是人与计算机的交互,就一定是使用的虚拟终端pty(pseudo-tty)

下面我们看一下Linux命令行输出的情况:
digdeep:~$ ls -l /dev/tty*
crw-rw-rw- 1 root tty     5,  0 2011-06-22 11:08 /dev/tty
crw--w---- 1 root root    4,  0 2011-06-22 11:08 /dev/tty0
crw------- 1 root root    4,  1 2011-06-22 11:08 /dev/tty1
crw--w---- 1 root tty     4, 10 2011-06-22 11:08 /dev/tty10
crw--w---- 1 root tty     4, 11 2011-06-22 11:08 /dev/tty11
crw--w---- 1 root tty     4, 12 2011-06-22 11:08 /dev/tty12
crw--w---- 1 root tty     4, 13 2011-06-22 11:08 /dev/tty13
crw--w---- 1 root tty     4, 14 2011-06-22 11:08 /dev/tty14
crw--w---- 1 root tty     4, 15 2011-06-22 11:08 /dev/tty15
crw--w---- 1 root tty     4, 16 2011-06-22 11:08 /dev/tty16
crw--w---- 1 root tty     4, 17 2011-06-22 11:08 /dev/tty17
crw--w---- 1 root tty     4, 18 2011-06-22 11:08 /dev/tty18
crw--w---- 1 root tty     4, 19 2011-06-22 11:08 /dev/tty19
crw------- 1 root root    4,  2 2011-06-22 11:08 /dev/tty2
crw--w---- 1 root tty     4, 20 2011-06-22 11:08 /dev/tty20
crw--w---- 1 root tty     4, 21 2011-06-22 11:08 /dev/tty21
crw--w---- 1 root tty     4, 22 2011-06-22 11:08 /dev/tty22
crw--w---- 1 root tty     4, 23 2011-06-22 11:08 /dev/tty23
crw--w---- 1 root tty     4, 24 2011-06-22 11:08 /dev/tty24
crw--w---- 1 root tty     4, 25 2011-06-22 11:08 /dev/tty25
crw--w---- 1 root tty     4, 26 2011-06-22 11:08 /dev/tty26
crw--w---- 1 root tty     4, 27 2011-06-22 11:08 /dev/tty27
crw--w---- 1 root tty     4, 28 2011-06-22 11:08 /dev/tty28
crw--w---- 1 root tty     4, 29 2011-06-22 11:08 /dev/tty29
crw------- 1 root root    4,  3 2011-06-22 11:08 /dev/tty3
crw--w---- 1 root tty     4, 30 2011-06-22 11:08 /dev/tty30
crw--w---- 1 root tty     4, 31 2011-06-22 11:08 /dev/tty31
crw--w---- 1 root tty     4, 32 2011-06-22 11:08 /dev/tty32
crw--w---- 1 root tty     4, 33 2011-06-22 11:08 /dev/tty33
crw--w---- 1 root tty     4, 34 2011-06-22 11:08 /dev/tty34
crw--w---- 1 root tty     4, 35 2011-06-22 11:08 /dev/tty35
crw--w---- 1 root tty     4, 36 2011-06-22 11:08 /dev/tty36
crw--w---- 1 root tty     4, 37 2011-06-22 11:08 /dev/tty37
crw--w---- 1 root tty     4, 38 2011-06-22 11:08 /dev/tty38
crw--w---- 1 root tty     4, 39 2011-06-22 11:08 /dev/tty39
crw------- 1 root root    4,  4 2011-06-22 11:08 /dev/tty4
crw--w---- 1 root tty     4, 40 2011-06-22 11:08 /dev/tty40
crw--w---- 1 root tty     4, 41 2011-06-22 11:08 /dev/tty41
crw--w---- 1 root tty     4, 42 2011-06-22 11:08 /dev/tty42
crw--w---- 1 root tty     4, 43 2011-06-22 11:08 /dev/tty43
crw--w---- 1 root tty     4, 44 2011-06-22 11:08 /dev/tty44
crw--w---- 1 root tty     4, 45 2011-06-22 11:08 /dev/tty45
crw--w---- 1 root tty     4, 46 2011-06-22 11:08 /dev/tty46
crw--w---- 1 root tty     4, 47 2011-06-22 11:08 /dev/tty47
crw--w---- 1 root tty     4, 48 2011-06-22 11:08 /dev/tty48
crw--w---- 1 root tty     4, 49 2011-06-22 11:08 /dev/tty49
crw------- 1 root root    4,  5 2011-06-22 11:08 /dev/tty5
crw--w---- 1 root tty     4, 50 2011-06-22 11:08 /dev/tty50
crw--w---- 1 root tty     4, 51 2011-06-22 11:08 /dev/tty51
crw--w---- 1 root tty     4, 52 2011-06-22 11:08 /dev/tty52
crw--w---- 1 root tty     4, 53 2011-06-22 11:08 /dev/tty53
crw--w---- 1 root tty     4, 54 2011-06-22 11:08 /dev/tty54
crw--w---- 1 root tty     4, 55 2011-06-22 11:08 /dev/tty55
crw--w---- 1 root tty     4, 56 2011-06-22 11:08 /dev/tty56
crw--w---- 1 root tty     4, 57 2011-06-22 11:08 /dev/tty57
crw--w---- 1 root tty     4, 58 2011-06-22 11:08 /dev/tty58
crw--w---- 1 root tty     4, 59 2011-06-22 11:08 /dev/tty59
crw------- 1 root root    4,  6 2011-06-22 11:08 /dev/tty6
crw--w---- 1 root tty     4, 60 2011-06-22 11:08 /dev/tty60
crw--w---- 1 root tty     4, 61 2011-06-22 11:08 /dev/tty61
crw--w---- 1 root tty     4, 62 2011-06-22 11:08 /dev/tty62
crw--w---- 1 root tty     4, 63 2011-06-22 11:08 /dev/tty63
crw--w---- 1 root root    4,  7 2011-06-22 11:08 /dev/tty7
crw--w---- 1 root tty     4,  8 2011-06-22 11:08 /dev/tty8
crw--w---- 1 root tty     4,  9 2011-06-22 11:08 /dev/tty9
crw-rw---- 1 root dialout 4, 64 2011-06-22 11:08 /dev/ttyS0
crw-rw---- 1 root dialout 4, 65 2011-06-22 11:08 /dev/ttyS1
crw-rw---- 1 root dialout 4, 66 2011-06-22 11:08 /dev/ttyS2
crw-rw---- 1 root dialout 4, 67 2011-06-22 11:08 /dev/ttyS3
digdeep:~$

digdeep:~$ ls -l /dev/pts/*
crw--w---- 1 digdeep tty  136, 0 2011-06-22 12:09 /dev/pts/0
crw--w---- 1 digdeep tty  136, 1 2011-06-22 12:14 /dev/pts/1
crw--w---- 1 digdeep tty  136, 2 2011-06-22 12:16 /dev/pts/2
c--------- 1 root    root   5, 2 2011-06-22 11:08 /dev/pts/ptmx


digdeep:~$ ps ax
......
  820 tty7     Rs+    0:09 /usr/bin/X :0 -nr -verbose -auth /var/run/gdm/auth-fo
  864 tty4     Ss+    0:00 /sbin/getty -8 38400 tty4
  868 tty5     Ss+    0:00 /sbin/getty -8 38400 tty5
  875 tty2     Ss+    0:00 /sbin/getty -8 38400 tty2
  876 tty3     Ss+    0:00 /sbin/getty -8 38400 tty3
  879 tty6     Ss+    0:00 /sbin/getty -8 38400 tty6
......
 1277 tty1     Ss+    0:00 /sbin/getty -8 38400 tty1
......
 1613 pts/0    Ss     0:00 bash

digdeep:~$ tty
/dev/pts/0

很显然我们是通过tty1登陆进来的。tty2到tty6已经启动等待其它用户的登陆。tty7用户权限的验证。
/dev/tty1对应的虚拟终端是/dev/pts/0 。
但是从:crw------- 1 root root    4,  1 2011-06-22 11:08 /dev/tty1
我们可以知道,我们根本无权访问/dev/tty1
然而从:crw-rw-rw- 1 root tty     5,  0 2011-06-22 11:08 /dev/tty
我们可以知道,任何用户对/dev/tty都有读写的权限
这样安排的原因是:实际上/dev/tty只是一个相当于“符号链接”,它实际的终端是某个它对应的
/dev/pts/n
。但是我们不知道这里的n到底是等于多少。实际上我们也不需要知道,需要访问终端时我们直接打开文件/dev/tty即可打开对应的/dev/pts/n .

/dev/tty文件的存在,有一个特殊的用法:
当标准输入stdin和标准输出stdout被重定向时,我们仍然可以通过/dev/tty文件而实现对键盘的读取和对显示器的输出!
下面的实例摘录自<>
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>

  4. #define PAGELEN 24
  5. #define LINELEN 512

  6. void do_more(FILE *);
  7. int see_more(FILE *);

  8. int main(int argc, char *argv[])
  9. {
  10.         FILE *fp;

  11.         if(argc == 1)
  12.                 do_more(stdin);
  13.         else{
  14.                 while(--argc){
  15.                         if((fp = fopen(*++argv, "r")) != NULL){
  16.                                 do_more(fp);
  17.                                 fclose(fp);
  18.                         }else
  19.                                 exit(1);
  20.                 }
  21.         }

  22.         return 0;
  23. }

  24. /*
  25.  * read PAGELEN lines, then call see_more() for further instructions.
  26.  */
  27. void do_more(FILE *fp)
  28. {
  29.         char line[LINELEN];
  30.         int num_of_lines = 0;
  31.         int see_more(), reply;
  32.         FILE *fp_tty;

  33.         fp_tty = fopen("/dev/tty", "r"); /* NEW: cmd stream */
  34.         if(fp_tty == NULL)
  35.                 exit(1);

  36.         while(fgets(line, LINELEN, fp)){ /* more input */
  37.                 if(num_of_lines == PAGELEN){ /* full screen ? */
  38.                         reply = see_more(fp_tty); /* y: ask user */
  39.                         if(reply == 0) /* n: done *? */
  40.                                 break;
  41.                         num_of_lines -= reply; /* reset count */
  42.                 }
  43.                 if(fputs(line, stdout) == EOF) /* show line */
  44.                         exit(1); /* or die */
  45.                 num_of_lines++; /* count it */
  46.         }
  47. }

  48. /*
  49.  * print message, wait for response, return # of lines to advance
  50.  * a means no, space means yes, CR means one line.
  51.  */
  52. int see_more(FILE *cmd) /* NEW: accepts arg */
  53. {
  54.         int c;

  55.         printf("\033[7m more? \033[m"); /* reverse on a vt100 */
  56.         while((c = getc(cmd)) != EOF){ /* get response */
  57.                 if(c == 'q') /* q -> N */
  58.                         return 0;
  59.                 if(c == ' ') /* ' ' -> next page */
  60.                         return PAGELEN; /* how many to show */
  61.                 if(c == '\n') /* Enter key -> 1 line */
  62.                         return 1;
  63.         }

  64.         return 0;
  65. }
编译:gcc -Wall -o more02 more02.c
执行:./more02 < more02.c
上面的执行我们对输入进行了重定向,但是我们还是可以通过/dev/tty来进行对键盘输入的读取
阅读(2572) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~