守护
进程(Daemon)是运行在
后台的一种特殊进程。它独立于控制
终端并且周期核瞎模性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进 程。Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任 务。比如,作业规划进程crond,打印进程lpd等。 \x0d\x0a守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相同,造成不同Unix环境下守护进程的编程规则并不一致。这需要读者注意,照搬 某些书上的规则(特别是BSD4.3和低版本的System V)到Linux会出现错误的。下面将全面介绍Linux下守护进程的编程要点并给出详细实例。 \x0d\x0a一. 守护进程及其特性 \x0d\x0a守护进程最重要的特性是后台运行。在这一点上DOS下的常驻内存程序TSR与之相似。其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的 文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。最后,守 护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端 (通常是shell)执行。 \x0d\x0a总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。如果读者对进程有比较深入的认识就更容易理解和编程了。 \x0d\x0a二. 守护进程的编程要点 \x0d\x0a前面讲过,不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一样,区别在于具体的实现细节不同。这个原则就是要满足守护 进程的特性。同时,Linux是基于Syetem V的SVR4并遵循Posix标准,实现起来与BSD4相比更方便。编程要点如下; \x0d\x0a1. 在后台运行。 \x0d\x0a为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。改缓 \x0d\x0aif(pid=fork()) \x0d\x0aexit(0)//是父进程,结束父进程,子进程继续 \x0d\x0a2. 脱离控制终端,登录会话和进程组 \x0d\x0a有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 \x0d\x0a控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: \x0d\x0asetsid()\x0d\x0a说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。 \x0d\x0a3. 禁止进程重新打开控制终端 \x0d\x0a现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端: \x0d\x0aif(pid=fork()) \x0d\x0aexit(0)//结束第一子进程,第二子进程继续(第二子进程不再是会话组长) \x0d\x0a4. 关闭打开的文件描述符 \x0d\x0a进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关神郑闭它们: \x0d\x0afor(i=0i 关闭打开的文件描述符close(i)>\x0d\x0afor(i=0i \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0avoid init_daemon(void) \x0d\x0a{ \x0d\x0aint pid\x0d\x0aint i\x0d\x0a\x0d\x0aif(pid=fork()) \x0d\x0aexit(0)//是父进程,结束父进程 \x0d\x0aelse if(pid \x0d\x0a#include \x0d\x0avoid init_daemon(void)//守护进程初始化函数 \x0d\x0amain() \x0d\x0a{ \x0d\x0aFILE *fp\x0d\x0atime_t t\x0d\x0ainit_daemon()//初始化为Daemon \x0d\x0awhile(1)//每隔一分钟向test.log报告运行状态 \x0d\x0a{ \x0d\x0asleep(60)//睡眠一分钟 \x0d\x0aif((fp=fopen("test.log","a")) >=0) \x0d\x0a{ \x0d\x0at=time(0)\x0d\x0afprintf(fp,"I'm here at %sn",asctime(localtime(&t)) )\x0d\x0afclose(fp)\x0d\x0a} \x0d\x0a} \x0d\x0a} \x0d\x0a以上程序在RedHat Linux6.0下编译通过。步骤如下: \x0d\x0a编译:gcc _g _o test init.c test.c \x0d\x0a执行:./test \x0d\x0a查看进程:ps _ef \x0d\x0a从输出可以发现test守护进程的各种特性满足上面的要求。
一、&
加在一个命令的最后,可以把这个命令放到后台执行,如:
[root@bqh-01 ~]# watch -n 3 "sh 1.sh " #每3s在后台执行一次 1.sh 脚本
二、ctrl + z
可以将一个正在前台执行的命令放到后台,并且处于辩誉暂停状态。
三、jobs
查看当前有多少在后台运行的命令
jobs -l选项可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated。但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识。
将后台中的命令调至 前台 继续运行。如果后台中有多个命令,可以用fg %jobnumber(是命令编号,不是进程号)将选中的命令调出。
五、bg
将一个在后台暂停的命令,变成在 后台 继续执行。如果后台中有多个命令,可以用bg %jobnumber将选中的命令调出。
六、kill
****
前台进程的终止:Ctrl+c
****七、 nohup
如果让程序始终在后台执行,即使关闭当前的终端也执行(之前的&做不到),这时候需要nohup。该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。关闭中断后,在另一个终端jobs已经无法看到后台跑得程序了,此时利用ps(进程查看命令悔森)
<pre style="margin: 0pxpadding: 0pxcolor: rgb(51, 51, 51)font-size: 14pxfont-style: normalfont-variant-ligatures: normalfont-variant-caps: normalfont-weight: 400letter-spacing: normalorphans: 2text-align: starttext-indent: 0pxtext-transform: nonewidows: 2word-spacing: 0px-webkit-text-stroke-width: 0pxbackground-color: rgb(255, 255, 255)text-decoration-style: initialtext-decoration-color: initial">ps -aux | grep "1.sh" #a:显示所有程序 u:以用户为主的格式携前段来显示 x:显示所有程序,不以终端机来区分</pre>
评论列表(0条)