如何处理在C中的Linux控制台按键?

我正在使用Linux控制台,我想做一个程序,输出随机字符,直到ESC按下。 我怎样才能使这样一个键盘处理程序?

Solutions Collecting From Web of "如何处理在C中的Linux控制台按键?"

getch()从Curses库或许? 此外,您将需要使用notimeout()告诉getch()不要等待下一个按键。

终端设备的线路规则默认工作在规范模式。 在这种模式下,终端驱动程序不会向用户空间显示缓冲区,直到看到换行符(按下Enter键)。

您可以通过使用tcsetattr()来操作termios结构,将终端设置为原始(非规范)模式。 分别清除ECHOICANON标志会禁用字符输入时的回显,并使读取请求直接从输入队列中满足。 将c_cc数组中的VTIMEVMIN的值设置为零将导致读取请求( fgetc() )立即返回,而不是块; 有效地投票stdin。 如果字符在流中不可用,对fgetc()的调用将返回EOF

 #define _XOPEN_SOURCE 700 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #include <time.h> int getkey() { int character; struct termios orig_term_attr; struct termios new_term_attr; /* set the terminal to raw mode */ tcgetattr(fileno(stdin), &orig_term_attr); memcpy(&new_term_attr, &orig_term_attr, sizeof(struct termios)); new_term_attr.c_lflag &= ~(ECHO|ICANON); new_term_attr.c_cc[VTIME] = 0; new_term_attr.c_cc[VMIN] = 0; tcsetattr(fileno(stdin), TCSANOW, &new_term_attr); /* read a character from the stdin stream without blocking */ /* returns EOF (-1) if no character is available */ character = fgetc(stdin); /* restore the original terminal attributes */ tcsetattr(fileno(stdin), TCSANOW, &orig_term_attr); return character; } int main() { int key; /* initialize the random number generator */ srand(time(NULL)); for (;;) { key = getkey(); /* terminate loop on ESC (0x1B) or Ctrl-D (0x04) on STDIN */ if (key == 0x1B || key == 0x04) { break; } else { /* print random ASCII character between 0x20 - 0x7F */ key = (rand() % 0x7F); printf("%c", ((key < 0x20) ? (key + 0x20) : key)); } } return 0; } 

注意:为了简单起见,此代码省略了错误检查。

更改一个按键的tty设置:

 int getch(void) { int c=0; struct termios org_opts, new_opts; int res=0; //----- store old settings ----------- res=tcgetattr(STDIN_FILENO, &org_opts); assert(res==0); //---- set new terminal parms -------- memcpy(&new_opts, &org_opts, sizeof(new_opts)); new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL); tcsetattr(STDIN_FILENO, TCSANOW, &new_opts); c=getchar(); //------ restore old settings --------- res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts); assert(res==0); return(c); } 
 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> char * me = "Parent"; void sigkill(int signum) { //printf("=== %s EXIT SIGNAL %d ===\n", me, signum); exit(0); } main() { int pid = fork(); signal(SIGINT, sigkill); signal(SIGQUIT, sigkill); signal(SIGTERM, sigkill); if(pid == 0) //IF CHILD { int ch; me = "Child"; while(1) { ch = (rand() % 26) + 'A'; // limit range to ascii AZ printf("%c",ch); fflush(stdout); // flush output buffer sleep(2); // don't overwhelm if (1 == getppid()) { printf("=== CHILD EXIT SINCE PARENT DIED ===\n"); exit(0); } } printf("==CHILD EXIT NORMAL==\n"); } else //PARENT PROCESS { int ch; if((ch = getchar())==27) kill(pid, SIGINT); //printf("==PARENT EXIT NORMAL (ch=%d)==\n", ch); } return(0); } 

在这个程序中,你只需要在esc char之后按enter ,因为getchar()是一个阻塞函数。 你也可以根据需要去除或减少孩子的睡眠时间。