
守护进程(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守护进程的各种特性满足上面的要求。ps命令用于查看系统中的进程状态,格式为:“ps [参数]”,
常见的ps命令参数包括有:
-a显示所有的进程(包括其他用户的)
-u用户以及其他详细信息
-x显示没有控制终端的进程
Linux系统中时刻运行着许许多多的进程,如果能够合理的管理它们,绝对有益于对系统的性能优化,Linux系统中进程最常见的5种不同的状态是运行、中断、不可中断、僵死与停止,它们的含义分别是:《Linux就该这么学》这本书上有详细的介绍,网址为
R(运行):正在运行或在运行队列中等待。
S(中断):休眠中, 在等待某个条件的形成或接收到信号。
D(不可中断):收到信号不唤醒和不可运行, 进程必须等待直到有中断发生。
Z:(僵死):进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放。
T:(停止):进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行。当执行"ps aux"命令后通常会看到下面格式的进程状态,表格中只是列举了部分输出值,而且正常的输出值中不包括中文注释部分:
ps是Linux 中最基础的浏览系统中的进程的命令。能列出系统中运行的进程,包括进程号、命令、CPU使用量、内存使用量等。接下来解读一下Linux *** 作系统的进程和Windows「Ctrl+Alt+delete」直接的差异。
在进行了解进程命令之前需要知道进程的一些状态
ps工具标识进程的5种状态码:
Linux *** 作系统进程执行的状态转换图如图所示:
下面来看一下 ps命令
ps --help命令可以查看ps命令的使用说明
或者使用 man ps命令 查询ps的详细说明
在 man手册 关于ps的解读中,总结了一下几个参数的含义:
以上的参数是可以拼接使用的,那就了解一些常用的参数组合
ps aux命令
ps -ef命令
查看进程状态这两个是命令是最常用的,使用 ps aux 可以查看进程的详细运行状态等。使用 ps -ef 不仅可以显示自身的PID,也可以显示PPID(父进程)。但是显示不了进程的运行状态
top命令
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器
man手册关于top的解释
关闭进程,重启进程
在上一片文章中 linux的目录结构 里面说过,在目录/etc/init.d/目录下包含许多系统各种服务的启动和停止脚本。假设进程占用内存较大或者进程异常,我们是重启这个进程restart。如下图所示:
我们重启了mysqld这个进程,可以看出进程号已经改变(从15743到15964),说明进程已经重启。
Linux下有3个特殊的进程,idle进程(PID=0), init进程(PID=1)和kthreadd(PID=2)
我们来看一下进程状态[下面是删减版,进程数量太多,列举一部分]
可以看到很多进程的PPID号是1和2。也就是init进程和kthreadd进程。
在使用Windows系统的过程中,都碰到过应用程序卡死的情况。应对此问题,我们一般都是等待失去响应的程序恢复,或者是直接使用任务管理器将其强制关闭,然后再重新打开。
在Linux中,遇到特别耗费资源的进程,当然需要使用 top命令 查看进程占用率高的进程。或者使用 free -m命令 查看内存剩余。假设需要强杀进程来释放空间。我们涉及到Linux中信号
评论列表(0条)