📄 00000018.htm
字号:
个子进程来处理实际的拨号。 <BR>2. 服务器端的精灵进程(父进程)一定要管理所有的加锁。 <BR> 图18.5 表示了这个过程的情况。 <BR>图18.5 调制解调器拨号器的工作过程 <BR> 服务器的工作过程如下: <BR>1. 父进程在它的服务端口,接收从客户端发来的请求。如我们在15.5节中所述, <BR>这在客户机-服务器之间生成了一个流管道。父进程就象15.6节中的open server一 <BR>样,要同时处理多个客户机。 <BR>2. 基于 客户端要联系的远程系统的名字,父进程查询Systems文件和Devices文 <BR>件找到匹配的项。父进程同时也维护一个加锁表,记录哪些设备在被使用,这样它 <BR>就不查询那些被使用的项了。 <BR>3. 如果发现匹配项,创建出子进程来进行实际的拨号。(父进程这时可以处理其 <BR>他客户端请求)。如果成功,子进程就在客户端指定的流管道上将调制解调器的文 <BR>件描述符传给客户端。(这个管道在fork时也被复制了),并调用exit(0)。如果 <BR>发生了错误(例如,电话线占线、没有响应等),子进程调用exit(1)。 <BR>4. 在子 进程结束时,会发送信号SIGCHLD通知父进程。父进程就得到子进程的结 <BR>束状态(waitpid)。 <BR> 如果子进程成功,父进程就不用再做其它事情。在客户端结束使用调制解调器 <BR>之前,必须一直对调制解调器加锁。客户端指定的客户端-父进程之间的流管道就 <BR>一直打开着。这样,当客户端终止时,父进程得到通知,然后释放对设备的加锁。 <BR> <BR> 如果子进程不成功,父进程就从Systems文件中尝试找下一个匹配项。如果找 <BR>到了对远程系统的另一项,父进程返回上一步,创建一个新的子进程来拨号。如果 <BR>没有找到新的匹配项,父进程调用send_err(见程序15.4)后关闭与客户端的流管 <BR>道。 <BR> 与每一个客户端有一个连接使子进程在必要时能将调试输出发回给客户端。发 <BR>生问题时,客户端常常想要看到整个实际拨号过程。 <BR>18.6 服务器端软件源代码 <BR>我们的服务器端软件共有17个文件。图18.6 详细说明了父进程和子进程所使用的 <BR>文件,以及这些文件中所包含的函数。图18.7描述了不同函数的调用过程。 <BR>Source file Parent Child Functions <BR>childdial.c <BR>cliargs.c <BR>client.c <BR>ctlstr.c <BR>debug.c <BR>devfile.c <BR>dialfile.c <BR>expectstr.c <BR>lock.c <BR>loop.c <BR>main.c <BR>request.c <BR>sendstr.c <BR>sigchld.c <BR>sysfile.c <BR>ttydial.c <BR>ttyopen.c <BR>P <BR>P <BR>P <BR>P <BR>P <BR>P <BR>P <BR>P <BR>P <BR> C <BR>C <BR>C <BR>C <BR>C <BR>C <BR>C <BR>C child_dial <BR>cli_args <BR>client_allc, client_add, client_del, client_sigchld <BR>ctl_str <BR>DEBUG, DEBUG_NONL <BR>dev_next, dev_rew, dev_find <BR>dial_next, dial_rew, dev_find <BR>expect_str, exp_read, sig_alrm <BR>find_line, lock_set, lock_rel, is_locked <BR>loop, cli_done, child_done <BR>main <BR>request <BR>send_str <BR>sig_chld <BR>sys_next, sys_rew, sys_posn <BR>tty_dial <BR>tty_open <BR>图18.6 服务器端源程序代码 <BR>图18.7 服务器端的函数调用过程 <BR> 程序18.1是call.h 头文件,它被包含在所有这些源程序文件中。call.h 包含 <BR>几个系统头文件,定义了一些基本的常量,声明了全局变量。 <BR>_______________________________________________________________________ <BR>_______ <BR>#include <sys/types.h> <BR>#include <errno.h> <BR>#include <signal.h> <BR>#include "ourhdr.h" <BR>#define CS_CALL "/home/stevens/calld" /* well-known name */ <BR>#define CL_CALL "call" <BR>#define MAXSYSNAME 256 <BR>#define MAXSPEEDSTR 256 <BR>#define NALLOC 10 /* #structs to alloc/realloc for <BR>*/ <BR> /* Client structs (client.c), Lock structs (lock.c) */ <BR>#define WHITE " \t\n" /* for separating tokens <BR>*/ <BR>#define SYSTEMS "./Systems" /* my own copies for now <BR>*/ <BR>#define DEVICES "./Devices" <BR>#define DIALERS "./Dialers" <BR> /* declare global variables */ <BR>extern int clifd; <BR>extern int debug; /* nonzero if interactive (not daemon) * <BR> <BR>extern int Debug; /* nonzero for dialing debug output */ <BR>extern char errmsg[]; /* error message string to return to cli <BR>nt */ <BR>extern char *speed; /* speed (actually "class") to use */ <BR>extern char *sysname; /* name of system to call */ <BR>extern uid_t uid; /* client's uid */ <BR>extern volatile sig_atomic_t chld_flag; /* when SIGCHLD occurs * <BR> <BR>extern enum parity { NONE, EVEN, ODD } parity; /* specified by client * <BR>/ <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -