The sample of O_ASYNC and aio_read
2007-09-27 10:20
609 查看
O_ASYNC 和 aio_read 示例代码, 主要用来示范Linux中的信号量.
代码为一个游戏,用*去捕捉小球,
Q --退出
S,s,F,f --加快或减缓小球x或y方向移动速度
z,x--改变小球x或y轴移动方向
i,j,k,l 移动*号.
bounce.h:
/**//* bounce.h
* somet settings for the game
*/
#ifndef bounce_h
#define bounce_h
#include <aio.h>
#include <curses.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define BLANK ' '
#define DFL_SYMBOL 'o'
#define PL_SYMBOL '*'
#define TOP_ROW 5
#define BOT_ROW 20
#define LEFT_EDGE 10
#define RIGHT_EDGE 70
#define X_INIT 10 // starting col
#define Y_INIT 10 // starting row
#define TICKS_PER_SEC 50 // affects speed
#define X_TTM 8
#define Y_TTM 8
int done = 0;
int score = 0;
// the ping pong ball
struct ppball...{
int y_pos,x_pos,
y_ttm,x_ttm,
y_ttg,x_ttg,
y_dir,x_dir;
char symbol;
};
// the player
struct player ...{
int y_pos,x_pos;
char symbol;
};
struct aiocb kbcbuf;
struct ppball the_ball;
struct player the_player;
int set_ticker(int);
void draw_wall();
void draw_score();
void draw_player();
void move_player(char);
#endif
bounce2d.c:
/**//* bounce2d 1.0
* bounce a character (defaults is 'o') around the screen
* defined by some paraments
*
* user input:
* s slow down x component, S: slow y component
* f speed up x component, F: speed y component
* Q quit
*
* purpose animation with use control, using aio_read() or O_ASYNC
* timer tick sends SIGALRM, handler does animation
* keybords sends SIGIO
* main only class pause()
* build: cc bounce2d.c set_ticker.c -lcurses -l rt-o bounce2d
*/
#include "bounce.h"
// the main loop
void set_up();
void wrap_up();
int main() ...{
set_up();
while(!done) // the main loop
pause();
wrap_up();
return 0;
}
/**//*
* init structure and other stuff
*/
void set_up() ...{
void ball_move(int);
void enable_kdb_signals();
void setup_aio_buffer();
void on_input(int);
// setup the ball's state
the_ball.y_pos = Y_INIT;
the_ball.x_pos = X_INIT;
the_ball.y_ttg = the_ball.y_ttm = Y_TTM;
the_ball.x_ttg = the_ball.x_ttm = X_TTM;
the_ball.y_dir = 1;
the_ball.x_dir = 1;
the_ball.symbol = DFL_SYMBOL;
done = 0;
initscr(); // setup the screen
noecho();
crmode();
clear();
// setup the player's state and draw the player
the_player.x_pos = LEFT_EDGE;
the_player.y_pos = TOP_ROW;
the_player.symbol = PL_SYMBOL;
draw_player();
// draw the wall
draw_wall();
// setup and draw the score
score = 0;
draw_score();
signal(SIGINT,SIG_IGN);
mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol);
refresh();
signal(SIGIO,on_input); // install a handler
// use O_ASYNC
// enable_kdb_signals(); // turn on kbd signals
// use aio_read
setup_aio_buffer(); // initialize aio ctrl buff
aio_read(&kbcbuf); // place a read quest
signal(SIGALRM,ball_move); // install alarm handler
set_ticker(1000/TICKS_PER_SEC); // send millisecs per tick
}
void wrap_up() ...{
set_ticker(0);
endwin(); // put back normal
}
void ball_move(int signum) ...{
int y_cur,x_cur,moved;
int bounce_or_lose(struct ppball *);
signal(SIGALRM,ball_move); // don't get caught now
y_cur = the_ball.y_pos; // old spot
x_cur = the_ball.x_pos;
moved = 0;
if(the_ball.y_ttm > 0 && --the_ball.y_ttg == 0) ...{
the_ball.y_pos += the_ball.y_dir; // move
the_ball.y_ttg = the_ball.y_ttm; // reset
moved = 1;
}
if(the_ball.x_ttm > 0 && --the_ball.x_ttg == 0) ...{
the_ball.x_pos += the_ball.x_dir; // move
the_ball.x_ttg = the_ball.x_ttm; // reset
moved = 1;
}
if(moved) ...{
mvaddch(y_cur,x_cur,BLANK);
// mvaddch(y_cur,x_cur,BLANK);
mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol);
if(bounce_or_lose(&the_ball)) ...{
++score;
draw_score();
draw_wall();
}
move(LINES - 1,COLS - 1);
refresh();
}
signal(SIGALRM,ball_move); // for unreliable systems
}
int bounce_or_lose(struct ppball *bp) ...{
int return_val = 0;
if(bp -> y_pos <= TOP_ROW) ...{
bp -> y_dir = 1;
} else if(bp -> y_pos >= BOT_ROW) ...{
bp -> y_dir = -1;
}
if(bp -> x_pos <= LEFT_EDGE) ...{
bp -> x_dir = 1;
} else if(bp -> x_pos >= RIGHT_EDGE) ...{
bp -> x_dir = -1;
}
if(bp -> x_pos == the_player.x_pos
&& bp -> y_pos == the_player.y_pos)
return_val = 1;
return return_val;
}
/**//*
* intstall a handler, tell kernel who to notify on input, enable signals
*/
void enable_kdb_signals() ...{
int fd_flags;
fcntl(0,F_SETOWN,getpid());
fd_flags = fcntl(0,F_GETFL);
fcntl(0,F_SETFL,(fd_flags | O_ASYNC));
}
/**//*
* handler called to when aio_read() has stuff to read
* First check for any errors codes, and if ok, then get the return code
*/
void on_input(int signum) ...{
int c;
while((c = getchar()) != 'Q') ...{
if(c == 'f') --the_ball.x_ttm;
else if(c == 's') ++the_ball.x_ttm;
else if(c == 'F') --the_ball.y_ttm;
else if(c == 'S') ++the_ball.y_ttm;
else if(c == 'z')
the_ball.x_dir = -the_ball.x_dir;
else if(c == 'x')
the_ball.y_dir = -the_ball.y_dir;
else if(c == 'i' || c == 'j' || c == 'k' || c == 'l')
move_player(c);
}
done = 1;
}
/**//*
* set memebers of struct
* First specify args like those for read(fd,buf,num) and offset
* Then specify what to do(send signal) and what signal(SIGIO)
*/
void setup_aio_buffer() ...{
static char input[1]; // 1 char of input
// describe what to read
kbcbuf.aio_fildes = 0; // standard input
kbcbuf.aio_buf = input; // buffer
kbcbuf.aio_nbytes = 1; // number to read
kbcbuf.aio_offset = 0; // offset in file
// describe what to do when read is ready
kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
kbcbuf.aio_sigevent.sigev_signo = SIGIO; // send SIGIO
}
/**//*
* draw the wall when setup.
*/
void draw_wall() ...{
int i,j;
// draw four corner
mvaddch(TOP_ROW - 1,LEFT_EDGE - 1,'+');
mvaddch(BOT_ROW + 1,LEFT_EDGE - 1,'+');
mvaddch(TOP_ROW - 1,RIGHT_EDGE + 1,'+');
mvaddch(BOT_ROW + 1,RIGHT_EDGE + 1,'+');
// draw top row
for(i = LEFT_EDGE,j = TOP_ROW - 1; i <= RIGHT_EDGE; ++i) ...{
mvaddch(j,i,'-');
}
// draw left column
for(i = LEFT_EDGE - 1,j = TOP_ROW; j <= BOT_ROW; ++j) ...{
mvaddch(j,i,'|');
}
// draw botton row
for(i = LEFT_EDGE,j = BOT_ROW + 1; i <= RIGHT_EDGE; ++i) ...{
mvaddch(j,i,'-');
}
// draw right column
for(i = RIGHT_EDGE + 1,j = TOP_ROW; j <= BOT_ROW; ++j) ...{
mvaddch(j,i,'|');
}
}
/**//*
* draw score on the left top corner
*/
void draw_score() ...{
char score_string[100];
sprintf(score_string,"score:%d",score);
move(1,1);
addstr(score_string);
}
/**//*
* draw the player
*/
void draw_player() ...{
mvaddch(the_player.y_pos,the_player.x_pos,the_player.symbol);
}
/**//*
* move the player
*/
void move_player(char input) ...{
mvaddch(the_player.y_pos,the_player.x_pos,BLANK);
switch(input) ...{
case 'i':
if(the_player.y_pos > TOP_ROW)
--the_player.y_pos;
break;
case 'k':
if(the_player.y_pos < BOT_ROW)
++the_player.y_pos;
break;
case 'j':
if(the_player.x_pos > LEFT_EDGE)
--the_player.x_pos;
break;
case 'l':
if(the_player.x_pos < RIGHT_EDGE)
++the_player.x_pos;
break;
}
draw_player();
}
set_ticker.c:
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
/**//*
* set_ticker.c
* set_ticker( number_of_milliseconds )
* arranges for the interval timer to issue
* SIGALRM's at regular intervals
* returns -1 on error, 0 for ok
*
* arg in milliseconds, converted into micro seoncds
*/
int set_ticker( int n_msecs )
...{
struct itimerval new_timeset;
long n_sec, n_usecs;
n_sec = n_msecs / 1000 ;
n_usecs = ( n_msecs % 1000 ) * 1000L ;
new_timeset.it_interval.tv_sec = n_sec; /**//* set reload */
new_timeset.it_interval.tv_usec = n_usecs; /**//* new ticker value */
new_timeset.it_value.tv_sec = n_sec ; /**//* store this */
new_timeset.it_value.tv_usec = n_usecs ; /**//* and this */
return setitimer(ITIMER_REAL, &new_timeset, NULL);
}
makefile:
bounce2d: bounce2d.c bounce.h set_ticker.c
gcc $^ -l curses -l rt -o $@ -Wall
代码为一个游戏,用*去捕捉小球,
Q --退出
S,s,F,f --加快或减缓小球x或y方向移动速度
z,x--改变小球x或y轴移动方向
i,j,k,l 移动*号.
bounce.h:
/**//* bounce.h
* somet settings for the game
*/
#ifndef bounce_h
#define bounce_h
#include <aio.h>
#include <curses.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define BLANK ' '
#define DFL_SYMBOL 'o'
#define PL_SYMBOL '*'
#define TOP_ROW 5
#define BOT_ROW 20
#define LEFT_EDGE 10
#define RIGHT_EDGE 70
#define X_INIT 10 // starting col
#define Y_INIT 10 // starting row
#define TICKS_PER_SEC 50 // affects speed
#define X_TTM 8
#define Y_TTM 8
int done = 0;
int score = 0;
// the ping pong ball
struct ppball...{
int y_pos,x_pos,
y_ttm,x_ttm,
y_ttg,x_ttg,
y_dir,x_dir;
char symbol;
};
// the player
struct player ...{
int y_pos,x_pos;
char symbol;
};
struct aiocb kbcbuf;
struct ppball the_ball;
struct player the_player;
int set_ticker(int);
void draw_wall();
void draw_score();
void draw_player();
void move_player(char);
#endif
bounce2d.c:
/**//* bounce2d 1.0
* bounce a character (defaults is 'o') around the screen
* defined by some paraments
*
* user input:
* s slow down x component, S: slow y component
* f speed up x component, F: speed y component
* Q quit
*
* purpose animation with use control, using aio_read() or O_ASYNC
* timer tick sends SIGALRM, handler does animation
* keybords sends SIGIO
* main only class pause()
* build: cc bounce2d.c set_ticker.c -lcurses -l rt-o bounce2d
*/
#include "bounce.h"
// the main loop
void set_up();
void wrap_up();
int main() ...{
set_up();
while(!done) // the main loop
pause();
wrap_up();
return 0;
}
/**//*
* init structure and other stuff
*/
void set_up() ...{
void ball_move(int);
void enable_kdb_signals();
void setup_aio_buffer();
void on_input(int);
// setup the ball's state
the_ball.y_pos = Y_INIT;
the_ball.x_pos = X_INIT;
the_ball.y_ttg = the_ball.y_ttm = Y_TTM;
the_ball.x_ttg = the_ball.x_ttm = X_TTM;
the_ball.y_dir = 1;
the_ball.x_dir = 1;
the_ball.symbol = DFL_SYMBOL;
done = 0;
initscr(); // setup the screen
noecho();
crmode();
clear();
// setup the player's state and draw the player
the_player.x_pos = LEFT_EDGE;
the_player.y_pos = TOP_ROW;
the_player.symbol = PL_SYMBOL;
draw_player();
// draw the wall
draw_wall();
// setup and draw the score
score = 0;
draw_score();
signal(SIGINT,SIG_IGN);
mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol);
refresh();
signal(SIGIO,on_input); // install a handler
// use O_ASYNC
// enable_kdb_signals(); // turn on kbd signals
// use aio_read
setup_aio_buffer(); // initialize aio ctrl buff
aio_read(&kbcbuf); // place a read quest
signal(SIGALRM,ball_move); // install alarm handler
set_ticker(1000/TICKS_PER_SEC); // send millisecs per tick
}
void wrap_up() ...{
set_ticker(0);
endwin(); // put back normal
}
void ball_move(int signum) ...{
int y_cur,x_cur,moved;
int bounce_or_lose(struct ppball *);
signal(SIGALRM,ball_move); // don't get caught now
y_cur = the_ball.y_pos; // old spot
x_cur = the_ball.x_pos;
moved = 0;
if(the_ball.y_ttm > 0 && --the_ball.y_ttg == 0) ...{
the_ball.y_pos += the_ball.y_dir; // move
the_ball.y_ttg = the_ball.y_ttm; // reset
moved = 1;
}
if(the_ball.x_ttm > 0 && --the_ball.x_ttg == 0) ...{
the_ball.x_pos += the_ball.x_dir; // move
the_ball.x_ttg = the_ball.x_ttm; // reset
moved = 1;
}
if(moved) ...{
mvaddch(y_cur,x_cur,BLANK);
// mvaddch(y_cur,x_cur,BLANK);
mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol);
if(bounce_or_lose(&the_ball)) ...{
++score;
draw_score();
draw_wall();
}
move(LINES - 1,COLS - 1);
refresh();
}
signal(SIGALRM,ball_move); // for unreliable systems
}
int bounce_or_lose(struct ppball *bp) ...{
int return_val = 0;
if(bp -> y_pos <= TOP_ROW) ...{
bp -> y_dir = 1;
} else if(bp -> y_pos >= BOT_ROW) ...{
bp -> y_dir = -1;
}
if(bp -> x_pos <= LEFT_EDGE) ...{
bp -> x_dir = 1;
} else if(bp -> x_pos >= RIGHT_EDGE) ...{
bp -> x_dir = -1;
}
if(bp -> x_pos == the_player.x_pos
&& bp -> y_pos == the_player.y_pos)
return_val = 1;
return return_val;
}
/**//*
* intstall a handler, tell kernel who to notify on input, enable signals
*/
void enable_kdb_signals() ...{
int fd_flags;
fcntl(0,F_SETOWN,getpid());
fd_flags = fcntl(0,F_GETFL);
fcntl(0,F_SETFL,(fd_flags | O_ASYNC));
}
/**//*
* handler called to when aio_read() has stuff to read
* First check for any errors codes, and if ok, then get the return code
*/
void on_input(int signum) ...{
int c;
while((c = getchar()) != 'Q') ...{
if(c == 'f') --the_ball.x_ttm;
else if(c == 's') ++the_ball.x_ttm;
else if(c == 'F') --the_ball.y_ttm;
else if(c == 'S') ++the_ball.y_ttm;
else if(c == 'z')
the_ball.x_dir = -the_ball.x_dir;
else if(c == 'x')
the_ball.y_dir = -the_ball.y_dir;
else if(c == 'i' || c == 'j' || c == 'k' || c == 'l')
move_player(c);
}
done = 1;
}
/**//*
* set memebers of struct
* First specify args like those for read(fd,buf,num) and offset
* Then specify what to do(send signal) and what signal(SIGIO)
*/
void setup_aio_buffer() ...{
static char input[1]; // 1 char of input
// describe what to read
kbcbuf.aio_fildes = 0; // standard input
kbcbuf.aio_buf = input; // buffer
kbcbuf.aio_nbytes = 1; // number to read
kbcbuf.aio_offset = 0; // offset in file
// describe what to do when read is ready
kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
kbcbuf.aio_sigevent.sigev_signo = SIGIO; // send SIGIO
}
/**//*
* draw the wall when setup.
*/
void draw_wall() ...{
int i,j;
// draw four corner
mvaddch(TOP_ROW - 1,LEFT_EDGE - 1,'+');
mvaddch(BOT_ROW + 1,LEFT_EDGE - 1,'+');
mvaddch(TOP_ROW - 1,RIGHT_EDGE + 1,'+');
mvaddch(BOT_ROW + 1,RIGHT_EDGE + 1,'+');
// draw top row
for(i = LEFT_EDGE,j = TOP_ROW - 1; i <= RIGHT_EDGE; ++i) ...{
mvaddch(j,i,'-');
}
// draw left column
for(i = LEFT_EDGE - 1,j = TOP_ROW; j <= BOT_ROW; ++j) ...{
mvaddch(j,i,'|');
}
// draw botton row
for(i = LEFT_EDGE,j = BOT_ROW + 1; i <= RIGHT_EDGE; ++i) ...{
mvaddch(j,i,'-');
}
// draw right column
for(i = RIGHT_EDGE + 1,j = TOP_ROW; j <= BOT_ROW; ++j) ...{
mvaddch(j,i,'|');
}
}
/**//*
* draw score on the left top corner
*/
void draw_score() ...{
char score_string[100];
sprintf(score_string,"score:%d",score);
move(1,1);
addstr(score_string);
}
/**//*
* draw the player
*/
void draw_player() ...{
mvaddch(the_player.y_pos,the_player.x_pos,the_player.symbol);
}
/**//*
* move the player
*/
void move_player(char input) ...{
mvaddch(the_player.y_pos,the_player.x_pos,BLANK);
switch(input) ...{
case 'i':
if(the_player.y_pos > TOP_ROW)
--the_player.y_pos;
break;
case 'k':
if(the_player.y_pos < BOT_ROW)
++the_player.y_pos;
break;
case 'j':
if(the_player.x_pos > LEFT_EDGE)
--the_player.x_pos;
break;
case 'l':
if(the_player.x_pos < RIGHT_EDGE)
++the_player.x_pos;
break;
}
draw_player();
}
set_ticker.c:
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
/**//*
* set_ticker.c
* set_ticker( number_of_milliseconds )
* arranges for the interval timer to issue
* SIGALRM's at regular intervals
* returns -1 on error, 0 for ok
*
* arg in milliseconds, converted into micro seoncds
*/
int set_ticker( int n_msecs )
...{
struct itimerval new_timeset;
long n_sec, n_usecs;
n_sec = n_msecs / 1000 ;
n_usecs = ( n_msecs % 1000 ) * 1000L ;
new_timeset.it_interval.tv_sec = n_sec; /**//* set reload */
new_timeset.it_interval.tv_usec = n_usecs; /**//* new ticker value */
new_timeset.it_value.tv_sec = n_sec ; /**//* store this */
new_timeset.it_value.tv_usec = n_usecs ; /**//* and this */
return setitimer(ITIMER_REAL, &new_timeset, NULL);
}
makefile:
bounce2d: bounce2d.c bounce.h set_ticker.c
gcc $^ -l curses -l rt -o $@ -Wall
相关文章推荐
- the simplest sample of listener.ora and tnsnames.ora
- Question 12: In C++, which of the following is the best declaration for an overloaded operator[] to allow read-only access (and
- The difference of static, readonly and const in C#
- 著名的安装制作软件InnoSetup的源码及示例源码-The installation of a well-known software s source code and sample InnoSetup source
- Async Performance: Understanding the Costs of Async and Await
- The promises and challenges of std::async task-based parallelism in C++11 C++11 std::async/future/promise
- Analysing the ASM code of a simple sample of C programming language at Linux Platform by GCC and GDB
- Read the book - Self Leadership and the One Minute Manager
- The Installation and Compilation of OpenCASCADE
- State of the "Art": A Taxonomy of Artistic Stylization Techniques for Images and Video(二)
- Sample of STL(Vector):begin and rbegin
- C++ and The Perils of Double-Checked Locking: Part I
- Given a set of n symbols a size k and a combination of length k of non repeating characters from the symbol set
- Debug error:"One or more breakpoints cannot be set and have been disabled.Execution will stop at the beginning of the program."
- Group and Capture Parts of the Match (归类和抓取匹配中某部分)
- [VOA美国人物] Kay Yow and Betty Jameson: They Changed the World of
- the macro of watch variable value and its memory content
- Zhao Jinglei: ReadSense Ltd Pay more attention to the commercialization of the ground, research AI c
- Step by Step Installation of the Subversion 1.x Server for Linux and Solaris 8/9/10 (English)
- The Future of Real-Time SLAM and Deep Learning vs SLAM