⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 390.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="314.htm">上一层</a>][<a href="391.htm">下一篇</a>]
<hr><p align="left"><small>发信人: Luther (天语≡怀恋华工), 信区: LINUX <br>

标  题: 也谈编写Unix的daemon程序 <br>

发信站: 武汉白云黄鹤站 (Sun May 28 03:29:46 2000), 站内信件 <br>

  <br>

────────────────────────────────────── <br>

─ <br>

【作者】冀卫东 <br>

     一、引言 <br>

     《微电脑世界》1997年第5期上刊登了一篇关于如何编写Unix daemon程序的文章, <br>

介绍 <br>

了编写daemon程序的几个编程准则,主要包括以下几点: <br>

     (1)使daemon进程不受后台作业I/O影响,让daemon进程忽略SIGTTOU、SIGTTIN、SI <br>

GTS <br>

T P信号; <br>

     (2)将daemon进程与它的原始进程组和控制终端脱离,采用setpgrp(),setsid()函数 <br>

调 <br>

用 ; <br>

     (3)关闭打开文件; <br>

     (4)将状态写入一磁盘文件; <br>

     (5)将当前目录改为根目录。 随着网络和客户机/服务器方式的普及,服务器上的d <br>

ae <br>

mon进程越来越多,性能要求也越来越高,除了以上几点外,还有一些应注意的事项,如不注 <br>

意 <br>

意 <br>

会降低daemon进程的性能甚至导致死机。这里对编写daemon程序作一些补充,供大家参考 <br>

。 <br>

     二、daemon编程应注意的几个问题 <br>

     1.应使daemon产生的子进程运行结束后消失 <br>

     daemon进程常常要产生子进程来响应客户机发来的请求,但这些子进程在运行完后 <br>

并不 <br>

消失,而是变为僵尸进程(zombie process)。如频繁响应客户机发来的请求,会使僵尸进 <br>

程过 <br>

多而导致速度变慢甚至死机。因为子进程运行结束后并不消失,而是等待daemon进程运行 <br>

终 <br>

止后消失。解决办法是让daemon进程忽略SIGCHLD信号,这样子进程运行完后会自动消失 <br>

。 <br>

     函数调用为SIGNAL(SIGCHLD,SIG-IGN) <br>

     2.daemon终止前应进行善后处理 <br>

     daemon进程在起动后通常要做初使化工作,如改变设置,重新设定参数,打开文件。 <br>

dae <br>

m on进程起动后,不可能无休止地运行下去,一般需通过信号使其终止。终止前,应注意恢 <br>

复 <br>

原设定,关闭文件。可采用以下方式: <br>

     workend() <br>

     { <br>

     close files;/*关闭文件*/ <br>



     restore old parameters;/*恢复原参数*/ <br>

     ...... /*其它参数恢复*/ <br>

     } <br>

     function() <br>

     { <br>

     ......... <br>

     SIGNAL(SIGTERM,workend); <br>

     SIGNAL(SIGQUIT,workend); <br>

     ........ <br>

     } <br>

     同时,中止daemon进程时,应使用SIGTERM(15),SIGQUIT(3)信号,避免使用SIGKILL( <br>

9), <br>

因其不可被捕捉,不会执行结束函数。 <br>

     3.定时强制中断 <br>

     daemon进程常要产生子进程来响应客户机发来的请求,有时处理客户请求的函数可 <br>

能不 <br>

太完善,会无休止的运行下去(如死循环)而不会返回,这样会使发出请求的客户进程无限 <br>

期等 <br>

待,造成客户机死机。解决办法是在客户机或服务器上增加超时检测机制,首先设定最大 <br>

处里 <br>

时间,当超过这一时间即终止运行,返回错误码。可采用以下方式: <br>

     #define MaxWaitTime 10 /*设定最大时间为10秒*/ <br>



     jmp-buf jmpenv; <br>

     int (*sign)(); <br>

     timeout() <br>

     { <br>

     longjmp(jmpenv,1); <br>

     }; <br>

     在子进程前部,设: <br>

     if (setjmp(jmpenv)!=0) <br>

     { <br>

     alarm(0);/* 恢复原ALARM()参数 */ <br>

     signal(SIGALRM,sign);/* 恢复原SIGNAL()参数 */ <br>

     ............... <br>

     return(-1); <br>

     }; <br>

     sign=signal(SIGALRM,timeout);/*设新信号函数*/ <br>

     alarm(MaxWaitTime); /*设最大等待时间*/ <br>

     process()......;/*程序处理*/ <br>

     alarm(0);/* 恢复原ALARM()参数 */ <br>

     signal(SIGALRM,sign);/* 恢复原SIGNAL()参数 */ <br>

     ...... <br>

     4.防止daemon进程重复起动 <br>

     由于daemon进程一般在后台运行,如不注意极易造成重复起动,最好在程序起动时能 <br>



自 <br>

行检测,发现后台程序已运行则自行终止。 <br>

     可编一SHELL程序来判断,程序名定为:TestDaemonExist: <br>

     DaemonNum=`ps -e|grep $1|wc -l` <br>

     if [ $DaemonNum -ge 2 ] <br>

     then <br>

     exit(1) #如daemon进程已起动,则返回1 <br>

     else <br>

     exit(0) #如daemon进程未起动,则返回0 <br>

     fi <br>

     在程序前部,增加一个判断 <br>

     if (system("TestDaemonExist Daemon-name")!=0) <br>

     { <br>

     printf("daemon进程已起动!!!"); <br>

     exit(0); <br>

     }; <br>

     5.客户机与服务器间的通讯应采用字符串(字节流)方式 <br>

     客户机与服务器间会频繁的有数据交换,这些数据包括各种数据类型,如整型、单精 <br>

度 <br>

、双精度、字符等类型,由于不同的机器间编译方式不同,因此各数据长度不同(如某些机 <br>

器 <br>

以 8字节对齐,不满8位则空位补齐,这样一个整数本来占2个字节,现在则占8个字节;而有 <br>



的 <br>

机器占2个字节),造成偏移量或结构大小错误,进而数值传错,不同的机器间交换尤其如此 <br>

。 <br>

解决办法是将参数统一改为字符串(字节流)方式传输,不同的项间增加分隔符,或固定长 <br>

度, <br>

使用时再转变为各种数据类型,这样才能保正数据交换正确。 <br>

     6.daemon进程同子进程间协调运行 <br>

     daemon进程产生子进程后,子进程继承父进程的参量,如文件描述符,变量值等。这 <br>

样, <br>

一个文件在父进程中被打开,在子进程中也被打开。如父子进程都向文件中写数据,则文 <br>

件以 <br>

最后关闭的进程写入的数据为准,其它进程写入的均无效。(如同多个用户用VI编辑同一 <br>

个文 <br>

件 ,结果以最后存盘的为准一样)。daemon进程和子进程应避免这种情况发生,一个进程 <br>

打开 <br>

一个文件时,其它进程应将其关闭。父子进程的参数传递可采用管道,共享存储区、消息 <br>

队列 <br>

等方式,还可通过信号量来协调运行。 <br>

     三、daemon本身程序的框架 <br>

     下面的程序仅仅是一个框架,将它编译链接成运行程序,结合1997年第5期上的daem <br>

on程 <br>

序,用以帮助daemon运行,即可实现一个完整的daemon程序。 <br>



     #define MaxWaitTime 10 /*设定最大时间为10秒*/ <br>

     jmp-buf jmpenv; <br>

     int (*sign)(); <br>

     timeout() <br>

     { <br>

     longjmp(jmpenv,1); <br>

     }; <br>

     workend() <br>

     { <br>

     close files;/*关闭文件*/ <br>

     restore old parameters;/*恢复原参数*/ <br>

     ...... /*其它参数恢复*/ <br>

     } <br>

     main()/*daemon程序*/ <br>

     { <br>

     if (system("TestDaemonExist Daemon-name")!=0) <br>

     { <br>

     printf("daemon进程已起动!!!"); <br>

     exit(0); <br>

     }; <br>

     signal(SIGCHLD ,sign);/* 使子进程运行完后消失 */ <br>

     signal(SIGTERM,workend);/*终止前做恢复*/ <br>



     signal(SIGQUIT,workend);/*终止前做恢复*/ <br>

     ............... <br>

     if (fork()=0)/*如果需产生子进程处理*/ <br>

     { <br>

     If (setjmp(jmpenv)!=0) <br>

     { <br>

     alarm(0);/* 恢复原ALARM()参数 */ <br>

     signal(SIGALRM,sign);/* 恢复原SIGNAL()参数 */ <br>

     ............... <br>

     return(-1);/*返回错误码*/ <br>

     }; <br>

     sign=signal(SIGALRM,timeout);/*设新信号函数*/ <br>

     alarm(MaxWaitTime); /*设最大等待时间*/ <br>

     process()......;/*程序处理*/ <br>

     alarm(0);/* 恢复原ALARM()参数 */ <br>

     signal(SIGALRM,sign);/* 恢复原SIGNAL()参数 */ <br>

     sign=signal(SIGALRM,timeout);/*设新信号函数*/ <br>

     alarm(MaxWaitTime); /*设最大等待时间*/ <br>

     process()......;/*程序处理*/ <br>

     alarm(0);/* 恢复原ALARM()参数 */ <br>

     signal(SIGALRM,sign);/* 恢复原SIGNAL()参数 */ <br>

     ...... <br>



     } <br>

     } <br>

     SHELL程序名定为:TestDaemonExist: <br>

     DaemonNum=`ps -e|grep $1|wc -l` <br>

     if [ $DaemonNum -ge 2 ] <br>

     then <br>

     exit(1) #如daemon进程已起动,则返回1 <br>

     else <br>

     exit(0) #如daemon进程未起动,则返回0 <br>

     fi <br>

     作为服务器程序,会遇到各种情况。为了能更好地运行,减少错误,应尽可能考虑完 <br>

全。 <br>

笔者用以上程序架构写了一些daemon程序,运行效果良好。 <br>

     (作者地址:中国银行山西省分行信息科技处,030001) <br>

-- <br>

※ Origin: 笑 书 亭 <bbs.zd.dhs.org> <br>

-- <br>

     焚我残躯,熊熊烈火. 生亦何欢,死亦何苦? <br>

     为善除恶,惟光明故. 喜乐悲愁,皆归尘土. <br>

     怜我世人,忧患实多! 怜我世人,忧患实多! <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="314.htm">上一层</a>][<a href="391.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -