分类:
2008-10-15 16:40:50
第六章 设备输入/输出控制
6.1 概述
UNIX将设备看成文件,这是UNIX的一大特色。这里需要介绍一个设备号的概念。设备特别文件与两个设备号有关-主设备号和次设备号。主设备号告诉操作系统,当涉及文件名时,将使用哪种设备类型。对于每一种类型的设备都有一段驻留在操作系统中的程序代码,以控制相应类型的设备,这段代码被称为"设备驱动程序"。次设备号被传递给设备驱动程序,这个号码用来决定使用哪种物理设备。例如,决定在一块多重驱动控制卡上,哪个磁盘驱动器将被访问,以及该磁盘驱动器中哪一部分将被使用;或者,当一个磁盘驱动器所请求的操作已经完成后,应该被恢复原状。几个设备(如同类型的磁盘驱动器)可以用同一个主设备号,但它们将有不同的次设备号。看下面的例子:
%ls -l /dev/ttyq*
crw--w---- 2 yds user 15, 1 2月 17日 09时03分 ttyq1
crw--w---- 2 yds user 15, 14 2月 16日 17时00分 ttyq14
%
上例中15是主设备号,1和14是次设备号。
用户可以使用系统提供的统一而且独立于设备的界面-对文件进行操作的系统调用来操作设备,而没有必要涉及设备的具体细节。大部分对文件进行操作的系统调用对它们仍起作用,例如,用open打开设备,用read/write对设备进行读/写,设备操作完成后,用close关闭设备。但有的系统调用在对设备文件进行操作时,其功效有所不同。如create及open的创建方式都不能创建设备文件。
6.2 设备输入/输出控制-ioctl系统调用
ioctl是UNIX系统专门提供的用于设备控制的系统调用。该系统调用与设备类型(即主设备号)相关。不同的设备,系统提供了不同的控制命令。
ioctl的调用格式是:
ioctl(int fd, int cmd,arg…)
说明:参数fd是一设备文件的文件描述字,cmd是控制命令,它与设备相关,不同类型的设备有不同的控制命令。参数arg没有固定的数据结构,它随cmd的不同而不同。
第七章 高级编程
7.1 处理信号
信号是UNIX进程间最基本的通讯手段,主要作用是实现进程间异步事件的通讯。信号是传送到进程的"软中断",它通知进程在它们的环境中出现了非正常事件。进程接收到信号后要进行处理,处理方式为以下四种之一:
(1)
缺省方式(SIG_DFL):这是进程对信号的一般处理方式,在无特殊情况下,进程在接收到信号后将终止执行。有一些信号,在终止进程运行前需将终止进程的正文段、数据段、user结构和栈段内容写到当前目录的core文件中,以备调试工具分析与使用。
(2)
忽略方式(SIG_IGN):进程接收到一个已指明忽略的信号,则将该信号清除后,立即返回,不在任何工作。信号SIGKILL不能被忽略。
(3) 保持方式(SIG_HOLD):当进程处于该方式时,将接收的信号保存起来,等该进程的保持方式解除后,再进行处理。
(4)
捕获方式(设置信号处理函数):这是用户设置的信号处理方式,当进程接收到这种信号时,执行用户设置的信号处理函数,执行完后,恢复现场,然后继续往下执行。
1. 常用信号种类
UNIX信号的种类很多,下面介绍一些最常用的信号:
SIGHUP 挂断。这是当控制终端被挂起时送到进程的信号。
SIGINT 中断。由键盘产生的中断。
SIGQUIT 退出。由键盘产生的中断。
SIGKILL 终止。这个信号不能被捕获、阻塞或忽略。
SIGALRM 定时信号。
SIGTERM 软件终止信号。
SIGUSR1 用户定义的信号1。
SIGUSR2 用户定义的信号2。
这些信号值的声明在/usr/include/sys/signal.h文件中。
2. 发送信号-kill系统调用
用户传送信号到进程的系统调用是kill,调用格式为:
#include
#include
int kill (pid_t pid, int sig);
说明:该系统调用把一个信号值为sig的信号发送给进程标识符为pid的相关进程。成功时返回0,失败时返回-1。
该调用执行成功与否,依赖于调用进程的有效用户标识符和参数pid的值,pid值的含义如下:
大于0:将信号发送给进程号等于pid的进程。
等于0:将信号发送给调用进程的同组进程(0和1进程除外)。
等于-1:将信号发送给实际用户标识符等于调用进程的有效用户标识符的所有进程(0和1进程除外),如调用进程的有效用户是超级用户,则将信号发送给除0和1进程外的所有进程。
非-1的负数:将信号发送给进程组标识符为pid的绝对值的所有进程。
在实际编程中,kill系统调用非常有用,具体说来:
·常用方式
kill(pid,SIGUSR1) 向进程号为pid的进程发送信号SIGUSR1
·用来判断进程是否存在:
if (kill(pid,0) == 0)
进程号为pid的进程存在;
else
进程号为pid的进程不存在!
·用来杀掉子进程
kill(pid,1) 杀掉进程号为pid的进程
2. 处理信号-signal系统调用
用户处理信号的系统调用是signal,调用格式为:
#include
void (*signal (int sig, void (*func)()))();
说明:参数sig是一个信号值,func定义了该信号的处理方式。该系统定义的功能是按func的定义设置调用进程对信号sig的处理方式。执行成功时,返回调用进程先前对信号sig处理方式的值,失败则返回-1。参数取值为SIG_DFL或SIG_IGN或用户信号处理函数的地址时,分别表示缺省方式、忽略方式和捕获方式。
3.pause系统调用
pause系统调用的格式为:
pause()
说明:该调用没有参数,其功能为使调用进程睡眠直到其接收到一信号为止。该系统调用的结果依赖于调用进程对接收到的信号的处理方式。
缺省方式:终止调用进程,pause无返回值;
忽略方式:进程不受该信号的影响,继续睡眠;
捕获方式:调用进程从信号处理函数返回后,继续往下执行。
4. 使用信号定时-alarm系统调用
系统调用alarm可以实现定时器的功能,调用格式为:
#include
unsigned alarm(unsigned sec);
说明:参数sec指定定时的时间间隔,以秒为单位。用户进程可以先通过signal调用指定SIGALRM信号对应的捕获函数,然后调用alarm来设定闹钟,在定时这段时间内做自己的工作。定时时间一到,进程就接收到一个SIGALRM信号,并执行该信号对应的捕获函数。系统调用alarm在多进程编程中非常有用。
7.2 管道通讯
用信号来处理异常事件或错误是非常合适的,但它用来处理进程之间的大量信息传送,就非常不适宜。为此,UNIX又提供了一种称为管道的机构,主要处理进程间的大量信息传送。所谓管道是指进程间连接起来的一条通讯通道。它也UNIX文件概念的一种推广,管道通讯的介质是文件,称为管道文件。用户可以用文件操作的有关系统调用来操作管道文件,从而简化管道应用程序的设计。管道的形象描述如下图:
write 写端 读端 read
管道是UNIX最强大而最有特色的性能之一,特别是在命令行这一级,它允许任意的命令被顺序连接起来。例如:
%who | wc -l
该命令通过管道把命令who的输出送给字计数程序wc,选项-l告诉wc只计算行数。通过wc最终输出的系统已注册的用户个数。
[1]