第7章 事件驱动编程:编写一个视频游戏
问题
游戏,操作系统面临的问题
解决问题
屏幕编程:curses库
curses内部有虚拟和实际屏幕,调用refresh将改动更新到实际屏幕,类似于磁盘缓存
时钟编程
●sleep(n):将当前进程挂起n秒,或者等待一个不能忽略的信号唤醒
sleep调用了Alarms,由三个步骤组成
1.signal(SIGALRM,handler);//将信号与函数连接,时间一到就发送信号到进程,然后调用函数
2.alarm(n);
3.pause();//挂起进程直到信号到达,任何信号都可以唤醒
●usleep(n):比sleep更精确,延时n微秒
●间隔计时器:每个进程有三个独立的计时器:真实、虚拟、实用
每个计时器有两个设置:初始间隔和重复间隔,每个间隔有秒数和微秒数,可以用系统调用getitimer与setitimer来读和设置。
一个系统只需要一个时钟,每个进程设置自己的计数时间,操作系统在每过一个时间片后为所有的计数器的数值递减。
信号处理
●信号的概念:Unix中的软件中断称为信号
●早期信号处理机制signal:
不足:1.每次捕获之后都要重新设置(捕鼠器)
2.不知道信号被发送的原因,只知道信号的类型
3.处理函数中不能安全的阻塞其他信号
●POSIX中用sigaction代替signal:
使用:newhandler为sigaction结构体,blocked为sigset_t信号集
防止数据损毁
当代码对数据操作被打断时可能导致数据的不完整,称这段代码为临界区。要决定好哪一段代码为临界区并保护这段代码,最简单的办法就是阻塞或者忽略那些要使用修改特定数据的信号。
●处理信号时阻塞信号
上文中的sa_mask
●进程中阻塞信号
在任何时候进程都有一些信号被阻塞,这个信号集称为信号挡板,通过sigprocmask可以修改此信号集。
输入信号:异步I/O
本章的例子都是设置间隔计时器,调用getch阻塞程序以等待键盘输入,效率比较低,采用异步I/O可以在还没有输入时做别的事情。
●使用O_ASYNC
1.使用fcntl的F_SETOWN命令告诉内核发送输入通知信号给当前进程,因为其他进程可能也连接键盘。
2.调用fcntl设置文件描述符0的O_ASYNC位打开输入信号
3.建立和设置键盘输入时被调用的处理函数。
4.循环调用pause等待来自计时器或输入的信号。
●使用aio_read