Linux使用O_ASYNC非同期IO実現


本文は1つの《Unix/Linuxプログラミング実践教程》P 219の現れたbugを検討して、Linuxの上でbounce_async.cプログラムコードの実行に失敗しました.
Unixには2つの非同期入力(asynchronous input)システムがある.
1つの方法は、入力が完了したときに信号を送信し、別のシステムは、入力が読み込まれたときに信号を送信する.UCB(BSD)におけるファイル記述ブロックのO_の設定ASYNCビットは第1の方法を実現する.
2つ目の方法は、aio_を呼び出すPOSIX規格です.read.
実験の第1の方法の時、私は本の中のコードを採用して、1つの弾球のプログラムで、それが“Q”を入力して正常に退出することができないことを発見しました
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <signal.h>
#include <fcntl.h>

#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~
[email protected]
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 silly as 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を使って実験をします.私たちはその違いに注意しなければなりません.