一、对终端进行读写
当一个程序在命令提示符中被调用时,
shell负责将标准输入和标准输出流连接到你的程序,
实现程序与用户间的交互。
 
1. 标准模式和非标准模式
在默认情况下,
只有用户按下回车键后,程序才能读到终端的输入。
在大多数情况下,这样做是有益的,
因为它允许用户使用退格键和删除键来纠正输入中的错误,
用户只在对自己在屏幕上看到的内容满意时,
才会按下回车键把键入的数据传递给程序。
这种方式称为规范模式或标准模式。
 
在这种方式下,
Linux会暂存用户输入的内容,
直到用户按下回车键,
然后将用户选择的字符及紧随其后的回车符一起传递给程序。
 
 
2. 与终端进行对话
Linux提供了一个特殊设备/dev/tty,
该设备始终是指向当前终端或当前登录会话。
 
二、termios结构
termios是在POSIX规范中定义的标准接口,
通过设置termios类型的数据结构中的值和使用一小组函数调用,
就可以对终端接口进行控制。
termios数据结构和相关函数调用都定义在头文件termios.h中。
 
可以被调整来影响终端的值按照不同的模式被分成如下几组:
输入模式
输出模式
控制模式
本地模式
特殊控制字符
 
最小的termios结构的典型定义如下:
  1. #include <termios.h>
  2. struct termios {
  3. tcflag_t c_iflag;
  4. tcflag_t c_oflag;
  5. tcflag_t c_cflag;
  6. tcflag_t c_lflag;
  7. cc_t c_cc[NCCS];
  8. };
结构成员名称与上面列出的5种参数类型相对应。
 
可以调用函数tcgetattr来初始化与一个终端对应的termios结构,
该函数的原型如下:
  1. #include <termios.h>
  2. int tcgetattr(int fd, struct termios *termios_p);
这个函数调用把当前终端接口变量的值写入termios_p参数指向的结构。
 
如果这些值其后被修改了,
可以通过调用函数tcsetattr来重新配置终端接口,
该函数的原型如下:
  1. #include <termios.h>
  2. int tcsetattr(int fd, int actions, const struct termios *termios_p);
参数actions控制修改方式,
共有3种修改方式:
  TCSANOW:   立刻对值进行修改
  TCSADRAIN: 等当前的输出完成后再对值进行修改
  FCSAFLUSH: 等当前的输出完成后再对值进行修改,
             但丢弃还未从read调用返回的当前可用的任何输入。
 
具体的模式的宏定义可以参见man帮助手册或相关文档。
 
1. 输入模式
termios结构中的c_iflag成员的标志对它们进行控制。
可用于c_iflag成员的宏如下所示:
❑ BRKINT: Generate an interrupt when a break condition (loss of connection) 
          is detected on the line
❑ IGNBRK: Ignore break conditions on the line
❑ ICRNL:  Convert a received carriage return to a newline
❑ IGNCR:  Ignore received carriage returns
❑ INLCR:  Convert received newlines to carriage returns
❑ IGNPAR: Ignore characters with parity errors
❑ INPCK:  Perform parity checking on received characters
❑ PARMRK: Mark parity errors
❑ ISTRIP: Strip (set to seven bits) all incoming characters
❑ IXOFF:  Enable software flow control on input
❑ IXON:   Enable software flow control on output
 
2. 输出模式
c_oflag成员的宏如下所示:
❑ OPOST:  Turn on output processing
❑ ONLCR:  Convert any output newline to a carriage return/line feed pair
❑ OCRNL:  Convert any output carriage return to a newline
❑ ONOCR:  No carriage return output in column 0
❑ ONLRET: A newline also does a carriage return
❑ OFILL:  Send fill characters to provide delays
❑ OFDEL:  Use DEL as a fill character, rather than NULL
❑ NLDLY:  Newline delay selection
❑ CRDLY:  Carriage return delay selection
❑ TABDLY: Tab delay selection
❑ BSDLY:  Backspace delay selection
❑ VTDLY:  Vertical tab delay selection
❑ FFDLY:  Form feed delay selection
 
3. 控制模式
c_cflag成员的宏如下所示:
❑ CLOCAL: Ignore any modem status lines.
❑ CREAD:  Enable the receipt of characters.
❑ CS5:    Use five bits in sent or received characters.
❑ CS6:    Use six bits in sent or received characters.
❑ CS7:    Use seven bits in sent or received characters.
❑ CS8:    Use eight bits in sent or received characters.
❑ CSTOPB: Use two stop bits per character, rather than one.
❑ HUPCL:  Hang up modem on close.
❑ PARENB: Enable parity generation and detection.
❑ PARODD: Use odd parity rather than even parity.
 
4. 本地模式
c_lflag成员的宏如下所示:
❑ ECHO:   Enable local echoing of input characters
❑ ECHOE:  Perform a Backspace, Space, Backspace combination on receiving ERASE
❑ ECHOK:  Perform erase line on the KILL character
❑ ECHONL: Echo newline characters
❑ ICANON: Enable canonical input processing (see the text following this list)
❑ IEXTEN: Enable implementation-specific functions
❑ ISIG:   Enable signals
❑ NOFLSH: Disable flush on queue
❑ TOSTOP: Send background processes a signal on write attempts
 
5. 特殊控制字符
c_cc数组:
标准模式中可使用的数组下标:
❑ VEOF:   EOF character
❑ VEOL:   EOL character
❑ VERASE: ERASE character
❑ VINTR:  INTR character
❑ VKILL:  KILL character
❑ VQUIT:  QUIT character
❑ VSUSP:  SUSP character
❑ VSTART: START character
❑ VSTOP:  STOP character
非标准模式中可使用的数组下标:
❑ VINTR:  INTR character
❑ VMIN:   MIN value
❑ VQUIT:  QUIT character
❑ VSUSP:  SUSP character
❑ VTIME:  TIME value
❑ VSTART: START character
❑ VSTOP:  STOP character
 
6. 终端速度
函数原型如下:
  1. #include <termios.h>
  2. speed_t cfgetispeed(const struct termios *);
  3. speed_t cfgetospeed(const struct termios *);
  4. int cfsetispeed(struct termios *, speed_t speed);
  5. int cfsetospeed(struct termios *, speed_t speed);
 
7. 其他函数
  1. #include <termios.h>
  2. int tcdrain(int fd);
  3. int tcflow(int fd, int flowtype);
  4. int tcflush(int fd, int in_out_selector);
三、ffmpeg对键盘响应程序的分析
main.c

  1. /*
  2. * \File
  3. * main.c
  4. * \Descript
  5. * Taken from ffmpeg,
  6. * implement for signal response function
  7. * \Author
  8. * Neo Yan
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <signal.h>
  13. #include <limits.h>
  14. #include <unistd.h>
  15. #include <fcntl.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/time.h>
  18. #include <termios.h>
  19. static struct termios oldtty;
  20. static int q_pressed = 0;
  21. static int verbose = 1;
  22. static int using_stdin = 0;
  23. static int run_as_daemon = 0;
  24. static volatile int received_sigterm = 0;
  25. static void term_init(void);
  26. static void term_exit(void);
  27. static void sigterm_handler(int sig);
  28. static int read_key(void);
  29. /*
  30. * \Func
  31. * main
  32. * \Descript
  33. *
  34. */
  35. int main(int argc, char **argv)
  36. {
  37. int index = 0;
  38. int key;
  39. if (!using_stdin)
  40. {
  41. if (verbose >= 0)
  42. printf("Perss [q] to stop, [?] for help\n");
  43. }
  44. term_init();
  45. for ( ; received_sigterm == 0; )
  46. {
  47. /* if 'q' pressed, exits */
  48. if (!using_stdin)
  49. {
  50. if (q_pressed)
  51. break;
  52. /* read_key() returns 0 on EOF */
  53. key = read_key();
  54. if (key == 'q')
  55. {
  56. printf("quit\n");
  57. break;
  58. }
  59. if (key == '+')
  60. {
  61. verbose++;
  62. printf("verbose = %d\n", verbose);
  63. }
  64. if (key == '-')
  65. {
  66. verbose--;
  67. printf("verbose = %d\n", verbose);
  68. }
  69. if (key == '?')
  70. {
  71. printf("key function\n"
  72. "? show this help\n"
  73. "+ increase verbosity\n"
  74. "- decrease verbosity\n"
  75. "q quit\n"
  76. );
  77. }
  78. }
  79. printf("index = %d\n", index++);
  80. sleep(1);
  81. }
  82. return 0;
  83. }
  84. static void term_init(void)
  85. {
  86. if (!run_as_daemon)
  87. {
  88. struct termios tty;
  89. tcgetattr(0, &tty);
  90. oldtty = tty;
  91. atexit(term_exit);
  92. tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
  93. |INLCR|IGNCR|ICRNL|IXON);
  94. tty.c_oflag |= OPOST;
  95. tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
  96. tty.c_cflag &= ~(CSIZE|PARENB);
  97. tty.c_cflag |= CS8;
  98. tty.c_cc[VMIN] = 1;
  99. tty.c_cc[VTIME] = 0;
  100. tcsetattr (0, TCSANOW, &tty);
  101. /* Quit (POSIX). */
  102. signal(SIGQUIT, sigterm_handler);
  103. }
  104. signal(SIGINT , sigterm_handler);
  105. signal(SIGTERM, sigterm_handler);
  106. }
  107. static void term_exit(void)
  108. {
  109. printf("%s\n", "TERMINATION");
  110. if (!run_as_daemon)
  111. tcsetattr(0, TCSANOW, &oldtty);
  112. }
  113. static void sigterm_handler(int sig)
  114. {
  115. received_sigterm = sig;
  116. q_pressed++;
  117. term_exit();
  118. }
  119. /*
  120. * \Func
  121. * read_key
  122. * \Descript
  123. * read a key without blocking
  124. */
  125. static int read_key(void)
  126. {
  127. int n = 1;
  128. unsigned char ch;
  129. struct timeval tv;
  130. fd_set rfds;
  131. if (run_as_daemon)
  132. return -1;
  133. FD_ZERO(&rfds);
  134. FD_SET(0, &rfds);
  135. tv.tv_sec = 0;
  136. tv.tv_usec = 0;
  137. n = select(1, &rfds, NULL, NULL, &tv);
  138. if (n > 0)
  139. {
  140. n = read(0, &ch, 1);
  141. if (n == 1)
  142. return ch;
  143. return n;
  144. }
  145. return -1;
  146. }
makefile
  1. OBJECTS = main.o
  2. CC = gcc
  3. CFLAG = -g
  4. ffmpeg_signal : $(OBJECTS)
  5. $(CC) $(CFLAG) -o ffmpeg_signal $(OBJECTS)
  6. main.o:
  7. .PHONY:clean
  8. clean:
  9. rm ffmpeg_signal $(OBJECTS)
    转载:http://blog.chinaunix.net/uid-26000296-id-3429028.html

ffmpeg键盘命令响应程序详解的更多相关文章

  1. telnet 命令使用方法详解,telnet命令怎么用

    telnet 命令使用方法详解,telnet命令怎么用? 文章类型:电脑教程 原创:天诺时空   什么是Telnet? 对于Telnet的认识,不同的人持有不同的观点,可以把Telnet当成一种通信协 ...

  2. Linux开机启动程序详解

    Linux开机启动程序详解我们假设大家已经熟悉其它操作系统的引导过程,了解硬件的自检引导步骤,就只从Linux操作系统的引导加载程序(对个人电脑而言通常是LILO)开始,介绍Linux开机引导的步骤. ...

  3. Linux开机启动程序详解[转]

    Linux开机启动程序详解 我们假设大家已经熟悉其它操作系统的引导过程,了解硬件的自检引导步骤,就只从Linux操作系统的引导加载程序(对个人电脑而言通常是LILO)开始,介绍Linux开机引导的步骤 ...

  4. linux系统设置服务开机启动3种方法,Linux开机启动程序详解

    linux系统设置服务开机启动 方法1:.利用ntsysv伪图形进行设置,利用root登陆 终端命令下输入ntsysv 回车:如下图     方法2:利用命令行chkconfig命令进行设置 简要说明 ...

  5. Linux如何实现开机启动程序详解(转)

    Linux开机启动程序详解我们假设大家已经熟悉其它操作系统的引导过程,了解硬件的自检引导步骤,就只从Linux操作系统的引导加载程序(对个人电脑而言通常是LILO)开始,介绍Linux开机引导的步骤. ...

  6. VLC命令行参数详解

    VLC命令行参数详解 2012-11-29 14:00 6859人阅读 评论(0) 收藏 举报 Usage: vlc [options] [stream] ...You can specify mul ...

  7. FFmpeg开发笔记(五):ffmpeg解码的基本流程详解(ffmpeg3新解码api)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  8. ping命令执行过程详解

    [TOC] ping命令执行过程详解 机器A ping 机器B 同一网段 ping通知系统建立一个固定格式的ICMP请求数据包 ICMP协议打包这个数据包和机器B的IP地址转交给IP协议层(一组后台运 ...

  9. Linux命令工具 top详解

    Linux命令工具 top详解 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.top是一个动态显示过程,即可以通过用户按键来不 ...

随机推荐

  1. 给<hr/>添加样式

    点线式 破折线式 直线式 双线式 脊线式 槽线式 内嵌效果的 突起效果的 border-top:10px 设置水平线的大小 <hr style=" border-top:5px dot ...

  2. 我的C++笔记(Hello World)

    其实在学习C++之前,是因为自己想学AI,但是发现好多AI教程都是使用C语言来进行讲解的,真心感觉到C真的计算机的基础语言行业的共同语言.至于为什么是C++,主要是C++是从C语言演变而来的,兼容C, ...

  3. 常用CSS代码片段常见css bug

    1.禁止文字被选中 .unselectable { -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select ...

  4. URLLib库使用

    Date: 2019-06-19 Author: Sun urllib ​ 在Python 3以后的版本中,urllib2这个模块已经不单独存在(也就是说当你import urllib2时,系统提示你 ...

  5. HDU1114 - Piggy-Bank

    Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. ...

  6. 训练1-U

    输入2个正整数A,B,求A与B的最小公倍数. Input 2个数A,B,中间用空格隔开.(1<= A,B <= 10^9) Output 输出A与B的最小公倍数. Sample Input ...

  7. 配置mysql允许远程访问

    1.进入 mysql: /usr/local/mysql/bin/mysql -u root -p 2.使用 mysql库 : use mysql; 3.查看用户表 : SELECT `Host`,` ...

  8. 使用Ansible安装部署nginx+php+mysql之安装mysql(3)

    三.使用Ansible安装mysql 1.mysq.yaml文件 - hosts: clong remote_user: root gather_facts: no tasks: # 安装rpm包 - ...

  9. weex手机端安全键盘

    github地址:weexSafeKeyboard 效果图: 技术依赖:框架:weex+vue 弹出层:weex-ui 图标:iconfont 说明:1.如果不想用到weex-ui,可以把inputk ...

  10. SpringMVC在对应绑定不同实体,但具有相同属性名的解决方案....

    在springmvc中,可以对前台传递过来的参数进行与后台实体绑定(第二种方式相对较好). 比如: 前台页面: <form action="${pageContext.request. ...