Unix-Linux编程实践教程——第七章
来源:互联网 发布:fast paxos java示例 编辑:程序博客网 时间:2024/05/16 01:45
章节概要
本章节介绍事件驱动编程以及curses库的使用和异步IO——aio
基本curses函数
- initscr() 初始化curses库和tty
- endwin() 关闭curses并重置tty
- refresh() 使屏幕按照你的意图显示,刷新画面
- move(r,c) 移动光标到屏幕(r,c)位置
- addstr(s) 在当前位置画字符串s
- addch(c) 在当前位置画字符c
- clear() 清屏
- standout() 启动standout模式(一般使屏幕反色)
- standend() 关闭standout模式
hello1.c
/********************************************************* > File Name: hello1.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 09时36分30秒 *********************************************************/#include<stdio.h>#include<curses.h>//简单实用curses库,显示helloworld//编译命令:gcc hello1.c -o hello1 -lcursesint main(){ initscr(); clear(); move(10,20); addstr("Hello,world"); move(LINES-1,0); refresh(); getch(); endwin(); return 0;}
hello2.c
/********************************************************** > File Name: hello2.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 09时36分30秒 **********************************************************/#include<stdio.h>#include<curses.h>//整个屏幕由黑白两色helloworld依次交替显现int main(){ initscr(); clear(); for(int i=0;i<LINES;++i){ move(i,i+i); if(i%2==1) standout(); addstr("Hello,world"); if(i%2==1) standend(); } refresh(); getch(); endwin(); return 0;}
hello3.c
/************************************************************ > File Name: hello3.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 09时36分30秒 ************************************************************/#include<stdio.h>#include<curses.h>#include<unistd.h>//字符串在屏幕自上而下逐行显示,每秒增加一行,反色和正常显示交替出现int main(){ initscr(); clear(); for(int i=0;i<LINES;++i){ move(i,i+i); if(i%2==1) standout(); addstr("Hello,world"); if(i%2==1) standend(); sleep(1); refresh(); } endwin(); return 0;}
hello4.c
/************************************************************ > File Name: hello4.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 09时36分30秒 ************************************************************/#include<stdio.h>#include<curses.h>#include<unistd.h>int main(){ initscr(); clear(); for(int i=0;i<LINES;++i){ move(i,i+i); if(i%2==1) standout(); addstr("Hello,world"); if(i%2==1) standend(); refresh(); sleep(1); //通过下面两步操作,清楚之前显示的字符串 move(i,i+i); addstr(" "); } endwin(); return 0;}
hello5.c
/************************************************************ > File Name: hello5.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 09时36分30秒 ************************************************************/#include<stdio.h>#include<curses.h>#include<unistd.h>//左右边界设定#define LEFTEDGE 10#define RIGHTEDGE 30#define ROW 10int main(){ char message[] = "Hello"; char blank[] = " "; int dir = +5; int pos = LEFTEDGE; initscr(); clear(); while(1){ move(ROW,pos); addstr(message); move(LINES-1,COLS-1); refresh(); sleep(1); move(ROW,pos); addstr(blank); pos += dir; //通过dir正负控制左右移动 if(pos>=RIGHTEDGE) dir = -7; if(pos<=LEFTEDGE) dir = +7; } endwin(); return 0;}
sleep1.c
/************************************************************* > File Name: sleep1.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 10时11分53秒 *************************************************************/#include<stdio.h>#include<signal.h>#include<unistd.h>//#define SHHHHint main(){ void wakeup(int); printf("about to sleep for 4 second\n"); //设置SIGALRM的处理函数 signal(SIGALRM,wakeup); //设置时钟 alarm(4); pause(); //挂起进程,任何信号都可唤醒进程 printf("Morning so soon?\n");}void wakeup(int signum){#ifndef SHHHH printf("Alarm received from kernel\n");#endif}
计时器
- ITIMER_REAL 计量真实真实,计时完发送SIGALRM消息
- ITIMER_VIRTUAL 只有进程在用户态运行才计时,计时完发送SIGALRM消息
- ITIMER_PROF 计时器在进程运行于用户态或由该进程调用而陷入和心态时计时。计时完发送SIGPROF消息
ticker_demo.c
/************************************************************* > File Name: ticker_demo.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 10时23分30秒 ************************************************************/#include<stdio.h>#include<sys/time.h>#include<signal.h>#include<unistd.h>#include<stdlib.h>int main(){ void countdown(int); int set_ticker(int); //设置SIGALRM的处理函数 signal(SIGALRM,countdown); //设置计时器 if(set_ticker(500)==-1){ perror("set_ticker"); }else{ while(1){ pause(); } } return 0;}void countdown(int signum){ static int num = 10; printf("%d..",num--); fflush(stdout); if(num<0){ printf("DONE!\n"); exit(0); }}int set_ticker(int n){ //itimerval结构体it_interval初始值it_value间隔值 struct itimerval new_timeset; long n_sec,n_usecs; n_sec = n/1000; n_usecs = (n%1000)*1000L; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; new_timeset.it_value.tv_sec = n_sec; new_timeset.it_value.tv_usec = n_usecs; //使用ITIMER_REAL计时器 return setitimer(ITIMER_REAL,&new_timeset,NULL);}
/*********************************************************** > File Name: sigdemo3.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 12时12分49秒 ***********************************************************/#include<stdio.h>#include<signal.h>#include<string.h>#include<unistd.h>#define INPUTLEN 100//这个程序用来测试多个信号传来时系统是怎么处理的int main(int ac,char* av[]){ void inthandler(int); void quithandler(int); char input[INPUTLEN]; int nchars; signal(SIGINT,inthandler); signal(SIGQUIT,quithandler); do{ printf("\nType a message\n"); nchars = read(0,input,(INPUTLEN-1)); if(nchars==-1){ perror("read returned an error"); }else{ input[nchars]='\0'; printf("You typed:%s",input); } }while(strncmp(input,"quit",4)!=0);}void inthandler(int signum){ printf("Received signal %d..waiting\n",signum); sleep(2); printf("Leaving inthandler\n");}void quithandler(int signum){ printf("Received signal %d..waiting\n",signum); sleep(3); printf("Leaving quithandler\n");}
sigactdemo.c
/************************************************************ > File Name: sigactdemo.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 12时35分47秒 *************************************************************/#include<stdio.h>#include<signal.h>#include<unistd.h>#define INPUTLEN 100//使用sigaction来处理多个信号的情况int main(){ struct sigaction newhandler; sigset_t blocked; void inthandler(int); char x[INPUTLEN]; //设置sa_handler来处理信号来时的应对方式 newhandler.sa_handler = inthandler; //设置sa_flags来通知内核处理信号的方式 newhandler.sa_flags = SA_RESETHAND|SA_RESTART; //清空blocked的位 sigemptyset(&blocked); //设置blocked的位 sigaddset(&blocked,SIGQUIT); //设置sa_mask来决定处理一个消息时是否阻塞其他信号 newhandler.sa_mask = blocked; if(sigaction(SIGQUIT,&newhandler,NULL)==-1) perror("sigaction"); else{ while(1){ fgets(x,INPUTLEN,stdin); printf("input:%s",x); } } return 0;}void inthandler(int s){ printf("Called with signal %d\n",s); sleep(2); printf("done handling signal %d\n",s);}
curses函数
- cbreak() and nocbreak(): 当 cbreak 模式被开启後, 除了 DELETE 或 CTRL等仍被视为特殊控制字元外一切输入的字元将立刻被一一读取.当处於 nocbreak 模式时, 从键盘输入的字元将被储存在 buffer 里直到输入 RETURN或 NEWLINE.
- 在较旧版的 curses 须呼叫 crmode(),nocrmode() 来取代 cbreak(),nocbreak()
- nl() and nonl(): 用来决定当输入资料时, 按下 RETURN 键是否被对应为 NEWLINE 字元 ( 如 /n ).而输出资料时, NEWLINE 字元是否被对应为 RETURN 和 LINDFEED系统预设是开启的.
- echo() and noecho():此函式用来控制从键盘输入字元时是否将字元显示在终端机上.系统预设是开启的.
bounce1d.c
/**************************************************************** > File Name: bounce1d.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 14时16分04秒 ***************************************************************/#include<stdio.h>#include<curses.h>#include<signal.h>#include<unistd.h>#include<string.h>#include<sys/time.h>#define MESSAGE "hello"#define BLANK " "int row;int col;int dir;int main(){ int delay; int ndelay; int c; void move_msg(int); int set_ticker(int); initscr(); crmode(); noecho(); clear(); row = 10; col = 0; dir = 1; delay = 200; move(row,col); addstr(MESSAGE); signal(SIGALRM,move_msg); set_ticker(delay); while(1){ ndelay = 0; c = getch(); if(c=='Q') break; if(c==' ') dir=-dir; if(c=='f'&&delay>2) ndelay=delay/2; if(c=='s') ndelay=delay*2; if(ndelay>0) set_ticker(delay=ndelay); } endwin(); return 0;}void move_msg(int signum){ signal(SIGALRM,move_msg); move(row,col); addstr(BLANK); col += dir; move(row,col); addstr(MESSAGE); refresh(); if(dir==-1&&col<=0){ dir = 1; }else if(dir==1&&(col+strlen(MESSAGE))>=COLS){ dir = -1; }}int set_ticker(int n){ struct itimerval new_timeset; long n_sec,n_usecs; n_sec = n/1000; n_usecs = (n%1000)*1000L; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; new_timeset.it_value.tv_sec = n_sec; new_timeset.it_value.tv_usec = n_usecs; return setitimer(ITIMER_REAL,&new_timeset,NULL);}
bounce.h
/*********************************************************** > File Name: bounce.h > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 14时41分47秒 ***********************************************************/#define BLANK ' '#define DFL_SYMBOL 'O'#define TOP_ROW 5#define BOT_ROW 20#define LEFT_EDGE 10#define RIGHT_EDGE 70#define X_INIT 10#define Y_INIT 10#define TICKS_PER_SEC 50#define X_TTM 5#define Y_TTM 8struct ppball{ int y_pos,x_pos, y_ttm,x_ttm, y_ttg,x_ttg, y_dir,x_dir; char symbol;};
bounce2d.c
/****************************************************** > File Name: bounce2d.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 14时16分04秒 *****************************************************/#include<stdio.h>#include<curses.h>#include<signal.h>#include<unistd.h>#include<string.h>#include<sys/time.h>#include "bounce.h"//将显示的主体封装在ppball结构体内struct ppball the_ball;void set_up();void wrap_up();void ball_move(int);int set_ticker(int);int bounce_os_lose(struct ppball*);int main(){ set_up(); 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++; } wrap_up(); return 0;}void set_up(){ 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 = the_ball.x_dir = 1; the_ball.symbol = DFL_SYMBOL; initscr(); noecho(); crmode(); signal(SIGINT,SIG_IGN); mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol); refresh(); signal(SIGALRM,ball_move); set_ticker(1000/TICKS_PER_SEC);}void wrap_up(){ set_ticker(0); endwin();}void ball_move(int signum){ int y_cur,x_cur,moved; signal(SIGALRM,SIG_IGN); y_cur = the_ball.y_pos; x_cur = the_ball.x_pos; moved = 0; if(the_ball.y_ttm>0&&the_ball.y_ttg--==1){ the_ball.y_pos += the_ball.y_dir; the_ball.y_ttg = the_ball.y_ttm; moved = 1; } if(the_ball.x_ttm>0&&the_ball.x_ttg--==1){ the_ball.x_pos += the_ball.x_dir; the_ball.x_ttg = the_ball.x_ttm; 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); bounce_os_lose(&the_ball); move(LINES-1,COLS-1); refresh(); } signal(SIGALRM,ball_move);}int bounce_os_lose(struct ppball* bp){ int return_val = 0; if(bp->y_pos==TOP_ROW){ bp->y_dir = 1; return_val = 1; }else if(bp->y_pos==BOT_ROW){ bp->y_dir = -1; return_val = 1; } if(bp->x_pos==LEFT_EDGE){ bp->x_dir = 1; return_val = 1; }else if(bp->x_pos==RIGHT_EDGE){ bp->x_dir = -1; return_val = 1; } return return_val;}int set_ticker(int n){ struct itimerval new_timeset; long n_sec,n_usecs; n_sec = n/1000; n_usecs = (n%1000)*1000L; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; new_timeset.it_value.tv_sec = n_sec; new_timeset.it_value.tv_usec = n_usecs; return setitimer(ITIMER_REAL,&new_timeset,NULL);}
bounce_async.c
/******************************************************** > File Name: bounce_async.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 15时56分49秒 ********************************************************/#include<stdio.h>#include<curses.h>#include<signal.h>#include<fcntl.h>#include<unistd.h>#include<sys/time.h>#include<string.h>#define MESSAGE "hello"#define BLANK " "int row = 10;int col = 0;int dir = 1;int delay = 200;int done = 0;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){ //以防万一,重置SIGALRM 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;}//fcntl设置异步IOvoid 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));}int set_ticker(int n){ struct itimerval new_timeset; long n_sec,n_usecs; n_sec = n/1000; n_usecs = (n%1000)*1000L; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; new_timeset.it_value.tv_sec = n_sec; new_timeset.it_value.tv_usec = n_usecs; return setitimer(ITIMER_REAL,&new_timeset,NULL);}int main(){ void on_alarm(int); void on_input(int); void enable_kbd_signals(); initscr(); crmode(); noecho(); clear(); //设置SIGIO的处理函数,从键盘来的字符到达,内核会向进程发送SIGIO信号 signal(SIGIO,on_input); enable_kbd_signals(); signal(SIGALRM,on_alarm); set_ticker(delay); move(row,col); addstr(MESSAGE); //循环调用pause,等待来自键盘和计时器的信号 while(!done){ pause(); } endwin();}
bounce_aio.c
关于AIO的使用与理解
- 慢慢聊Linux AIO
- linux下aio异步读写详解与实例
/************************************************** > File Name: bounce_aio.c > Author: Duke-wei > Mail: 13540639584@163.com > Created Time: 2017年10月11日 星期三 16时24分17秒 **************************************************//* * 同步阻塞I/O:用户进程进行I/O操作,一直阻塞到I/O操作完成为止。 * 同步非阻塞I/O:用户程序可以通过设置文件描述符的属性O_NONBLOCK,I/O操作可以立即返回,但是并不保证I/O操作成功。 * 异步事件阻塞I/O:用户进程可以对I/O事件进行阻塞,但是I/O操作并不阻塞。通过select/poll/epoll等函数调用来达到此目的。 * 异步时间非阻塞I/O:也叫做异步I/O(AIO),用户程序可以通过向发送I/O请求命令,不用带I/O事件真正发生,可以继续左另外的事情,等I/O操作完成,内核会通过函数回调或者信号机制通知进程。提高系统吞吐量。 */#include<stdio.h>#include<curses.h>#include<signal.h>#include<sys/time.h>#include<aio.h>#include<string.h>#include<unistd.h>#include<stdlib.h>#define MESSAGE "hello"#define BLANK " "int row = 10;int col = 0;int dir = 1;int delay = 200;int done = 0;struct aiocb kbcbuf;void on_input(int signum){ int c; char *cp = (char*)kbcbuf.aio_buf; if(aio_error(&kbcbuf)!=0) perror("reading failed"); else { if(aio_return(&kbcbuf)==1){ c = *cp; if(c=='Q'||c==EOF) done=1; else if(c==' ') dir = -dir; } } aio_read(&kbcbuf);}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 setup_aio_buffer(){ static char input[1]; kbcbuf.aio_fildes = 0; kbcbuf.aio_buf = input; kbcbuf.aio_nbytes = 1; kbcbuf.aio_offset = 0; kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL; kbcbuf.aio_sigevent.sigev_signo = SIGIO;}int set_ticker(int n){ struct itimerval new_timeset; long n_sec,n_usecs; n_sec = n/1000; n_usecs = (n%1000)*1000L; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; new_timeset.it_value.tv_sec = n_sec; new_timeset.it_value.tv_usec = n_usecs; return setitimer(ITIMER_REAL,&new_timeset,NULL);}int main(){ initscr(); crmode(); noecho(); clear(); signal(SIGIO,on_input); setup_aio_buffer(); aio_read(&kbcbuf); signal(SIGALRM,on_alarm); set_ticker(delay); mvaddstr(row,col,MESSAGE); while(!done) pause(); endwin();}
阅读全文
0 0
- Unix-Linux编程实践教程——第七章
- Unix-Linux编程实践教程——第二章
- Unix-Linux编程实践教程——第三章
- Unix-Linux编程实践教程——第四章
- Unix-Linux编程实践教程——第五章
- Unix-Linux编程实践教程——第六章
- Unix-Linux编程实践教程——第八章
- Unix-Linux编程实践教程——第九章
- Unix-Linux编程实践教程——第十章
- Unix-Linux编程实践教程——第十一章
- Unix-Linux编程实践教程——第十二章
- Unix-Linux编程实践教程——第十三章
- Unix-Linux编程实践教程——第十四章
- Unix-Linux编程实践教程——第十五章
- 《unix/linux编程实践教程》学习笔记:第七章 事件驱动编程:编写一个视频游戏
- Unix/Linux编程实践教程
- Unix/Linux编程实践教程
- Unix-linux编程实践教程
- 【JZOJ5407】Deep
- 文章标题
- 从零开始学电脑 2.1
- c文件操作之位置指针设置函数fseek
- 动态规划 最长公共子序列
- Unix-Linux编程实践教程——第七章
- Rhyme/Java 常用IO流总结
- axis2的使用(转载)
- Java中Volatile变量小结
- 20191021考试总结2
- 模板模式 template
- CCF CSP Markdown JAVA 201703-3
- ajax做json拼接
- Restricted Boltzmann Machine(限制玻尔兹曼机)