第7章 事件驱动编程:编写一个视频游戏

问题

游戏,操作系统面临的问题
第7章 事件驱动编程:编写一个视频游戏

解决问题

屏幕编程:curses库
curses内部有虚拟和实际屏幕,调用refresh将改动更新到实际屏幕,类似于磁盘缓存
第7章 事件驱动编程:编写一个视频游戏
时钟编程
●sleep(n):将当前进程挂起n秒,或者等待一个不能忽略的信号唤醒
 sleep调用了Alarms,由三个步骤组成
1.signal(SIGALRM,handler);//将信号与函数连接,时间一到就发送信号到进程,然后调用函数
2.alarm(n);
3.pause();//挂起进程直到信号到达,任何信号都可以唤醒

●usleep(n):比sleep更精确,延时n微秒

●间隔计时器:每个进程有三个独立的计时器:真实、虚拟、实用
第7章 事件驱动编程:编写一个视频游戏
第7章 事件驱动编程:编写一个视频游戏
 每个计时器有两个设置:初始间隔和重复间隔,每个间隔有秒数和微秒数,可以用系统调用getitimer与setitimer来读和设置。
第7章 事件驱动编程:编写一个视频游戏
 一个系统只需要一个时钟,每个进程设置自己的计数时间,操作系统在每过一个时间片后为所有的计数器的数值递减。

信号处理
●信号的概念:Unix中的软件中断称为信号
●早期信号处理机制signal:
第7章 事件驱动编程:编写一个视频游戏
不足:1.每次捕获之后都要重新设置(捕鼠器)
2.不知道信号被发送的原因,只知道信号的类型
3.处理函数中不能安全的阻塞其他信号

●POSIX中用sigaction代替signal:
第7章 事件驱动编程:编写一个视频游戏
第7章 事件驱动编程:编写一个视频游戏
第7章 事件驱动编程:编写一个视频游戏
第7章 事件驱动编程:编写一个视频游戏
使用:newhandler为sigaction结构体,blocked为sigset_t信号集
第7章 事件驱动编程:编写一个视频游戏

防止数据损毁
 当代码对数据操作被打断时可能导致数据的不完整,称这段代码为临界区。要决定好哪一段代码为临界区并保护这段代码,最简单的办法就是阻塞或者忽略那些要使用修改特定数据的信号。

●处理信号时阻塞信号
 上文中的sa_mask

●进程中阻塞信号
 在任何时候进程都有一些信号被阻塞,这个信号集称为信号挡板,通过sigprocmask可以修改此信号集。
第7章 事件驱动编程:编写一个视频游戏
第7章 事件驱动编程:编写一个视频游戏

输入信号:异步I/O
 本章的例子都是设置间隔计时器,调用getch阻塞程序以等待键盘输入,效率比较低,采用异步I/O可以在还没有输入时做别的事情。

第7章 事件驱动编程:编写一个视频游戏
●使用O_ASYNC
 1.使用fcntl的F_SETOWN命令告诉内核发送输入通知信号给当前进程,因为其他进程可能也连接键盘。
 2.调用fcntl设置文件描述符0的O_ASYNC位打开输入信号
 3.建立和设置键盘输入时被调用的处理函数。
 4.循环调用pause等待来自计时器或输入的信号。

●使用aio_read
第7章 事件驱动编程:编写一个视频游戏