📄 00000001.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER> <BR> 在 UNIX 系统发展应用程式入门(一) 王志祥 <BR> <BR> <BR>序言: <BR> <BR> <BR> 同学们可能或多或少在网路上抓过UNIX 或 X 视窗的应用程式, <BR>你是否曾想过这些程式是如何写的?或者更进一步,你是否也想自己写一个 <BR>大家都有兴趣去用的程式?不但可出名又可训练自己的程式设计能力. <BR> 在 DOS 之下,可能大部分的人写应用程式都没问题.可是换到 UNIX <BR>之後可能就因不熟悉而不会写了.本文即是以笔者上学期所写之 UNIX <BR>应用程式: FindMan 作为□例,期收抛砖引玉之效. <BR> <BR> <BR>关於 FindMan: <BR> <BR> FindMan 是一集合 FindMan 、ScanGirl 、CScanGirl 三项 Utility <BR>为一体的程式. 当初发展 FindMan 的动机是由於上机人数太多,往往为了 <BR>找一个人而伤眼睛地用力看 rusers 的输出.於是开始写 FindMan . 而当时正逢 <BR>HuntGirl(u8011093) 、Hunt(u7917043) 相继推出,由於正合交大大多数男生 <BR>的需求,因此造成轰动.本程式为了顺应潮流,加入了 ScanGirl <BR>及 CScangirl ( ScanGirl 中文版 ). 由於处理程序类似, 因此合并成一个程式, <BR>而以 link(UNIX Command: ln) 连结各项程式,程式再以第一个字母判断该执行何项程序. <BR> FindMan 自开放使用以来,目前每个月皆被使用了 6000 次以上. 其中有一个 <BR>有趣现象, 最初一个月, ScanGirl 的使用率是 FindMan 的两倍,後来 FindMan 逐 <BR>渐追上 ScanGirl, 现在 FindMan : ScanGirl 的使用率是 5:1 (FindMan 5xxx 次). <BR>这现象似乎显示交大人已不在如以前那样喜欢和女孩子 talk 了. <BR> <BR> <BR>有关在 UNIX 上写应用程式的技巧和注意事项: <BR> <BR> 在 UNIX 上写应用程式与在 DOS 下写程式不一样的地方有几点: <BR>1. UNIX 的 Signal 相当於 DOS 的 Interrupt. <BR>2. UNIX 有许多系统呼叫,可以做低阶的动作. <BR>3. UNIX 是多工的作业系统,我们可善用 UNIX 的这项能力. <BR>4. UNIX 有程序间通讯的能力, 它可做各多工程序间、甚至各工作站间的沟通. <BR> <BR> 当然, UNIX 的功能不只这 4 点, 读者以後可以後慢慢体会. <BR> <BR> <BR>FindMan 的 Initial 部份: <BR> <BR> 由於 FindMan 主程式太长(共 10 页),而且其中有些部份如不了解就不要使用, <BR>否则系统可能会 ...,而你的 account 就可能会 ...,(当然,此一部份我会特别注明.) <BR>所以,我只会附上重要部份的程式. <BR> 以下我会列出程式片段, 与比较奇特的变数宣告. 读者们最好遇到没看 <BR>过的命令时, 在 UNIX 里用 man 查. <BR> <BR> struct passwd *p; <BR> uid_t uid; <BR> <BR> uid = getuid(); <BR> if (!(p = getpwuid(uid))) { <BR> printf("Can't get user name !!\n"); <BR> exit(1); <BR> } <BR> strcpy(uname,p->pw_name); <BR> gethostname(hsnm,sizeof(hsnm)); <BR> if ( getlogin() == NULL ) { <BR> printf("This program is avai ....... is program..... \n"); <BR> exit(1); <BR> } <BR> <BR> 以上此部份是取得使用者的帐号(account) 与执行 FindMan 时的工作站名称. <BR>并判断使用者是否真的在线上(OnLine), 以 getlogin() 判断使用者若不在线上, <BR>则不让不在线上的使用者执行. 此法可防止使用者使用 rsh、at、cron 等命令. <BR> 再来是以执行档第一个英文字判断该 show 哪一种讯息、该执行哪一种程 <BR>式(记录在一个变数里,以此变数判断). 此部份简单,不再赘述. <BR> 接著是程式後的参数判断,程式如下: <BR> <BR> while ((n = getopt(argc,argv,"af:h")) != EOF) <BR> switch(n) { <BR> case 'a': <BR> aflg++; <BR> break; <BR> case 'f': <BR> fflg++; <BR> hostfl=optarg; <BR> break; <BR> case 'h': <BR> if (aflg || fflg || lflg || Hflg) <BR> errflg++; <BR> else <BR> hflg++; <BR> break; <BR> default: <BR> errflg++; <BR> } <BR> if (errflg) { <BR> printf("\nUsage: %s [-a] [-h] [-H] [-f FindHostName's FILE]\n",argv[0]); <BR> printf(" -h : short help\n"); <BR> printf(" -H : detail help\n"); <BR> exit(1); <BR> } <BR> if (hflg) { <BR> printf("\nUsage: %s [-a] [-h] [-H] [-f FindHostName's FILE]\n",argv[0]); <BR> exit(0); <BR> } <BR> <BR> 程式中的 getopt() 之中的 "af:h" 是参数的字. 其中的 ':' 表示参数 <BR>之後还要加的东东. 例如 -f 之後还要加 FindHostName's FILE, 所以 f 之後要有 ':'. <BR>附带一提,这里所介绍的功能,虽然 FindMan 也会 Show 出,但大部分皆为保留功能, <BR>并不能使用, 必须等我有空实在加上.届时我会 announce. <BR> 这部份所用的技巧可使程式能提供使用者多样的选择.程式中的 aflg、fflg <BR>等皆为旗标变数. 它可记录参数的状况. <BR> 再下来是根据变数决定程式要读取的 database(有 .look 及我的中英文 <BR> girl database), 并记录到我的记录档里.此部份程式亦略去不提. <BR> 接下来是 UNIX 的 Signal 之运用和子程序的建立. 当初之所以使用 fork <BR>建立许多子程序并使用复杂且吃 Load 的程序间通讯, 是因为如此可以家快速度. <BR>由於有时会有一些工作站当掉或无法回应 rusers 的 request,这些工作站即会 <BR>延迟 rusers □集资料的时间. 我的程式即可部份解决这个问题. 由主程序 fork 出 <BR>去的各子程序各自 rusers 一个工作站,先得到资料的程序先向主程序传送. <BR>(程序间传送需用程序间通讯的技巧) 如此就可不管那些不传资料的工作站了. <BR>所以我的 FindMan 常不按顺序 show 各工作站的资讯後,停了很久才结束便是 <BR>这个道理. 知道原理後,下次看到讯息出完停下时,不必苦等而可以 Ctrl-C 取 <BR>而代之. 现在由於计中的 rusers 改良过而不必再苦等.因此利用此技巧取代 <BR>复杂且耗 Load 的程序间通讯便成为我的下一个课题. <BR> □话少说,看下面的程式: <BR> <BR> signal(SIGCLD, SIG_IGN); <BR> signal(SIGINT, timeout); <BR> <BR> for (i=0; i<CM; i++) { <BR> if ((pid = fork()) == 0) { <BR> pitch(hosts[i]); <BR> break; <BR> } <BR> } <BR> if (pid != 0) <BR> { <BR> tmpp[0]=(char)0; <BR> tmpp[1]='\0'; <BR> catch(tmpp); <BR> if ((short)tmpp[0]) { <BR> printf("There are %d workstation responding fail...\n",tmpp[0]); <BR> printf(" Fail workstation: %s\n",&tmpp[1]); <BR> } <BR> <BR> 前两个 Signal,第一个的意义是忽略子程序结束的讯号.而第二个的意义是 <BR>遇到 Ctrl-C 之类的中断时要执行 timeout() 函数.而底下则是用 fork() 产生 <BR>子程序,有关 fork() 的意义与用法,请自行参考资料. 程式中的 catch() 是我定义 <BR>的函数,下次再说.而 tmpp[0] 则是用来判断工作站是否有 respond. <BR> <BR> <BR> <BR>结语: <BR> <BR> 由於篇幅及时间因素,本文在此告一段落 ,下期再继续.若有任何建议,欢迎用 <BR>E-Mail 寄到 <A HREF="mailto:u7911093@cc.nctu.edu.tw">u7911093@cc.nctu.edu.tw</A> . <BR> <BR><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -