本文探讨一个《Unix/Linux编程实践教程》P219出现的bug,在Linux上bounce_async.c程序代码运行失败。
Unix有两个异步输入(asynchronous input)系统。
一种方法是当输入就绪时发送信号,另一个系统当输入被读入时发送信号。UCB(BSD)中通过设置文件描述块(file descriptor)的O_ASYNC位来实现第一种方法。
第二种方法是POSIX标准,它调用aio_read。
实验第一种方法时,我采用书中代码,就是一个弹球程序,发现了其不能在键入"Q"正常退出
#include
#include
#include
#include
#include
#define MESSAGE "hello"
#define BLANK" "
int row=10;
int col =0;
int dir =1;
int delay =200;
int done =0;
int main()
{
void on_alarm(int);
void on_input(int);
void enable_kbd_signals();
sigset_t * set;
set=(sigset_t*)malloc(sizeof(set));
sigemptyset(set);
sigaddset(set,SIGIO);
sigprocmask(SIG_UNBLOCK, set, NULL);
initscr();
crmode();
noecho();
clear();
enable_kbd_signals();
signal(SIGIO,(on_input));
enable_kbd_signals();
signal(SIGALRM,on_alarm);
set_ticker(delay);
move(row,col);
addstr(MESSAGE);
while(!done)
{
pause();
}
endwin();
}
void on_input(int signum)
{
int c = getch();
if(c=='Q'||c==EOF)
done=1;
else if(c==' ')
dir=-dir;
}
void on_alarm(int signum)
{
signal(SIGALRM,on_alarm);
mvaddstr(row,col,BLANK);
col+=dir;
mvaddstr(row,col,MESSAGE);
refresh();
if(dir==-1&&col<=0)
dir=1;
else if(dir==1&&col+strlen(MESSAGE)>=COLS)
dir=-1;
}
void enable_kbd_signals()
{
int fd_flags;
fcntl(0,F_SETOWN,getpid());
fd_flags=fcntl(0,F_GETFL);
fcntl(0,F_SETFL,(fd_flags|O_ASYNC));
}
遇到这个问题后,我很困惑,于是邮件问了作者Bruce Molay,没想到他神速的回复了我的邮件!兴奋异常!
下面我贴出的回复,这不算侵权吧,@Bruce Molay~
bmolay@gmail.com
Dear Scott,
Thank you for writing. The reason that 'Q' does not get you out of the program
is that on this version of Linux (and on most, I think) the signal handler is called,
the 'Q' is read, the done variable is set but the program never returns from pause().
Which is sillyas pause is supposed to block until a signal is handled.
One solution is to change the on_input() function to call endwin and exit if the input
is 'Q' or EOF.
if ( c == 'Q' || c == EOF ){
done = 1;
move(LINES-1,0);
endwin();
exit(0);
}
I checked it, and pause returns once, but never returns again. The signal
handlers are called and processed but pause does not return.
Try the aio one. that one works. I think async version is not supported on Linux very well.
他的英文还是很好懂的。真是很大家风范,大家以后遇到问题也可以多联系作者,It is so cool!!
Linux和Unix有一定的区别,在学习Unix的过程中,我们经常使用Linux做实验,我们需要注意其区别!