Linux 版 (精华区)

发信人: netiscpu (夜☆星光点点☆), 信区: Linux
标  题: ◇ 在 UNIX 系统发展应用程式入门 (一)
发信站: 紫 丁 香 (Sun Nov  8 18:44:54 1998), 转信


寄信人: guest.bbs@hgluo.hust.edu.cn 
标  题: ◇ 在 UNIX 系统发展应用程式入门 (一)
发信站: 华南理工大学 BBS木棉站
日  期: Thu Feb 20 14:13:19 1997

  在 UNIX 系统发展应用程式入门(一)                王志祥


序言:


        同学们可能或多或少在网路上抓过UNIX 或 X 视窗的应用程式,
你是否曾想过这些程式是如何写的?或者更进一步,你是否也想自己写一个
大家都有兴趣去用的程式?不但可出名又可训练自己的程式设计能力.
        在 DOS 之下,可能大部分的人写应用程式都没问题.可是换到 UNIX
之後可能就因不熟悉而不会写了.本文即是以笔者上学期所写之 UNIX
应用程式: FindMan 作为□例,期收抛砖引玉之效.


关於 FindMan:

        FindMan 是一集合 FindMan 、ScanGirl 、CScanGirl 三项 Utility
为一体的程式.  当初发展 FindMan 的动机是由於上机人数太多,往往为了
找一个人而伤眼睛地用力看 rusers 的输出.於是开始写 FindMan . 而当时正逢
HuntGirl(u8011093) 、Hunt(u7917043) 相继推出,由於正合交大大多数男生
的需求,因此造成轰动.本程式为了顺应潮流,加入了 ScanGirl
及 CScangirl ( ScanGirl 中文版 ). 由於处理程序类似, 因此合并成一个程式,
而以 link(UNIX Command: ln) 连结各项程式,程式再以第一个字母判断该执行何项程序.
        FindMan 自开放使用以来,目前每个月皆被使用了 6000 次以上. 其中有一个
有趣现象, 最初一个月, ScanGirl 的使用率是 FindMan 的两倍,後来 FindMan 逐
渐追上 ScanGirl, 现在 FindMan : ScanGirl 的使用率是 5:1 (FindMan 5xxx 次).
这现象似乎显示交大人已不在如以前那样喜欢和女孩子 talk 了.


有关在 UNIX 上写应用程式的技巧和注意事项:

        在 UNIX 上写应用程式与在 DOS 下写程式不一样的地方有几点:
1. UNIX 的 Signal 相当於 DOS 的 Interrupt.
2. UNIX 有许多系统呼叫,可以做低阶的动作.
3. UNIX 是多工的作业系统,我们可善用 UNIX 的这项能力.
4. UNIX 有程序间通讯的能力, 它可做各多工程序间、甚至各工作站间的沟通.

        当然, UNIX 的功能不只这 4 点, 读者以後可以後慢慢体会.


FindMan 的 Initial 部份:

        由於 FindMan 主程式太长(共 10 页),而且其中有些部份如不了解就不要使用,
否则系统可能会 ...,而你的 account 就可能会 ...,(当然,此一部份我会特别注明.)
所以,我只会附上重要部份的程式.
        以下我会列出程式片段, 与比较奇特的变数宣告. 读者们最好遇到没看
过的命令时, 在 UNIX 里用 man 查.

     struct passwd *p;
     uid_t uid;

     uid = getuid();
     if (!(p = getpwuid(uid))) {
        printf("Can't get user name !!\n");
        exit(1);
     }
     strcpy(uname,p->pw_name);
     gethostname(hsnm,sizeof(hsnm));
       if ( getlogin() == NULL ) {
         printf("This program is avai ....... is program..... \n");
           exit(1);
       }

        以上此部份是取得使用者的帐号(account) 与执行 FindMan 时的工作站名称.
并判断使用者是否真的在线上(OnLine), 以 getlogin() 判断使用者若不在线上,
则不让不在线上的使用者执行. 此法可防止使用者使用 rsh、at、cron 等命令.
        再来是以执行档第一个英文字判断该 show 哪一种讯息、该执行哪一种程
式(记录在一个变数里,以此变数判断). 此部份简单,不再赘述.
        接著是程式後的参数判断,程式如下:

        while ((n = getopt(argc,argv,"af:h")) != EOF)
                switch(n) {
                case 'a':
                        aflg++;
                        break;
                case 'f':
                        fflg++;
                        hostfl=optarg;
                        break;
                case 'h':
                        if (aflg || fflg || lflg || Hflg)
                                errflg++;
                        else
                                hflg++;
                        break;
                default:
                        errflg++;
                }
     if (errflg) {
       printf("\nUsage: %s [-a] [-h] [-H] [-f FindHostName's FILE]\n",argv[0]);
       printf("        -h : short help\n");
       printf("        -H : detail help\n");
       exit(1);
     }
     if (hflg) {
       printf("\nUsage: %s [-a] [-h] [-H] [-f FindHostName's FILE]\n",argv[0]);
       exit(0);
     }

        程式中的 getopt() 之中的 "af:h" 是参数的字. 其中的 ':' 表示参数
之後还要加的东东. 例如 -f 之後还要加 FindHostName's FILE, 所以 f 之後要有 ':'.
附带一提,这里所介绍的功能,虽然 FindMan 也会 Show 出,但大部分皆为保留功能,
并不能使用, 必须等我有空实在加上.届时我会 announce.
        这部份所用的技巧可使程式能提供使用者多样的选择.程式中的 aflg、fflg
等皆为旗标变数. 它可记录参数的状况.
        再下来是根据变数决定程式要读取的 database(有 .look 及我的中英文
 girl database), 并记录到我的记录档里.此部份程式亦略去不提.
        接下来是 UNIX 的 Signal 之运用和子程序的建立. 当初之所以使用 fork
建立许多子程序并使用复杂且吃 Load 的程序间通讯, 是因为如此可以家快速度.
由於有时会有一些工作站当掉或无法回应 rusers 的 request,这些工作站即会
延迟 rusers □集资料的时间. 我的程式即可部份解决这个问题. 由主程序 fork 出
去的各子程序各自 rusers 一个工作站,先得到资料的程序先向主程序传送.
(程序间传送需用程序间通讯的技巧) 如此就可不管那些不传资料的工作站了.
所以我的 FindMan 常不按顺序 show 各工作站的资讯後,停了很久才结束便是
这个道理. 知道原理後,下次看到讯息出完停下时,不必苦等而可以 Ctrl-C 取
而代之. 现在由於计中的 rusers 改良过而不必再苦等.因此利用此技巧取代
复杂且耗 Load 的程序间通讯便成为我的下一个课题.
        □话少说,看下面的程式:

     signal(SIGCLD, SIG_IGN);
     signal(SIGINT, timeout);

     for (i=0; i<CM; i++) {
         if ((pid = fork()) == 0) {
             pitch(hosts[i]);
             break;
          }
     }
     if (pid != 0)
        {
        tmpp[0]=(char)0;
        tmpp[1]='\0';
        catch(tmpp);
        if ((short)tmpp[0]) {
          printf("There are %d workstation responding fail...\n",tmpp[0]);
          printf(" Fail workstation: %s\n",&tmpp[1]);
        }

        前两个 Signal,第一个的意义是忽略子程序结束的讯号.而第二个的意义是
遇到 Ctrl-C 之类的中断时要执行 timeout() 函数.而底下则是用 fork() 产生
子程序,有关 fork() 的意义与用法,请自行参考资料. 程式中的 catch() 是我定义
的函数,下次再说.而 tmpp[0] 则是用来判断工作站是否有 respond.



结语:

        由於篇幅及时间因素,本文在此告一段落 ,下期再继续.若有任何建议,欢迎用
E-Mail 寄到 u7911093@cc.nctu.edu.tw .

--
m;32m※ 转寄:.华南网木棉站 bbs.gznet.edu.cn.[FROM: mtlab.hit.edu.cn]
--

                              Enjoy Linux!
                          -----It's FREE!-----

※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: mtlab.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.519毫秒