• ffmpeg键盘命令响应程序详解


    一、对终端进行读写
    当一个程序在命令提示符中被调用时,
    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 ");
    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 ");
    57.         break;
    58.       }
    59.       if (key == '+') 
    60.       {
    61.         verbose++;
    62.         printf("verbose = %d ", verbose);
    63.       }
    64.       if (key == '-')
    65.       { 
    66.         verbose--;
    67.         printf("verbose = %d ", verbose);
    68.       }
    69.       if (key == '?')
    70.       {
    71.         printf("key function " 
    72.                "? show this help " 
    73.                "+ increase verbosity " 
    74.                "- decrease verbosity " 
    75.                "q quit "
    76.                );
    77.        }
    78.     }
    79.     printf("index = %d ", 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 ", "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
  • 相关阅读:
    CentOS7.2安装mysql
    中国古代研究
    2018计算机考研各科试卷分值分布
    《期刊杂志总结》
    《认识雅思》
    《认识托福》
    Java框架
    英语学习方法
    单词2
    Phaser游戏框架与HTML Dom元素之间的通信交互
  • 原文地址:https://www.cnblogs.com/canphp/p/4465254.html
Copyright © 2020-2023  润新知