📄 00000004.htm
字号:
的身份。 <BR> <BR> 接下来的几行是一些信息,如CPU和内存的使用情况等等,第八栏是进程的执行状态, <BR>标有S说明这个进程正处于睡眠中,R表示进程处于运行中,而T表示进程被阻止,正在等 <BR>待一个CONT信号让它重新投入运行。 <BR> <BR> 在这里提到了信号这个词,信号大致就是系统向进程发出一个通知,警告它必须尽快 <BR>去处理某些事情。在UNIX中定义了许多信号,但和普通用户及管理员关系最密切的有下 <BR>面这样一些: <BR> <BR> 信号ID 名称 含义 是否可以捕获 是否可以阻塞? <BR> <BR> 1 SIGHUP 挂起 是 是 <BR> <BR> 2 SIGINT 中断 是 是 <BR> <BR> 3 SIGQUIT` 退出 是 是 <BR> <BR> 9 SIGKILL 杀死进程 否 否 <BR> <BR> 15 SIGTERM 软件终止 是 是 <BR> <BR> 如果想了解关于信号的详细内容,可以参考linux头文件中的signal.h。实际上,对于 <BR>最终用户,signal更多地用来杀死某个不应该被执行的进程,这是通过执行kill或者ki <BR>llall命令实现的。 <BR> <BR> kill命令用来向进程发送一个信号,其语法是 <BR> <BR> kill [-信号] 进程ID <BR> <BR> 其中的信号可以使用信号ID或者信号名,使用信号名时,前缀SIG省略,如果不明确地 <BR>给出信号,那么使用信号SIGTERM。尽管技术上可以用kill向进程发送任何信号,但是实 <BR>际上这个命令几乎总是用于杀死进程。进程ID就是在ps ax中看到的进程pid,例如,在 <BR>上面的例子中,杀死portmap程序的命令是 <BR> <BR> kill 358 <BR> <BR> 或者 <BR> <BR> kill –15 358 <BR> <BR> 或者 <BR> <BR> kill –TERM 358 <BR> <BR> 因为SIGTERM信号可以被捕获和阻塞,所以一个设计好的程序可以不理睬这个信号,如 <BR>果要杀死这样的程序,可以使用SIGKILL信号,如: <BR> <BR> kill –9 358 <BR> <BR> 或者 <BR> <BR> kill –KILL 358 <BR> <BR> 使用pid对许多人可能是不方便的,另外,可能有一个程序的多个拷贝在内存中执行, <BR>一个一个地杀死这些程序有时是很讨厌的事情,为此,Linux提供了killall命令。kill <BR>all和kill基本等同,但是它使用进程名而不是pid来发送信号,因此可以一次杀死所有 <BR>同名进程。 <BR> <BR> kill –l或者killall –l将显示所有可用的信号。 <BR> <BR> 有一个信号SIGTSTP用于定义“键盘阻止”。处于某些原因,你可能想暂停当前的某个 <BR>工作而去进行某个更重要的工作,这可以通过按下^Z来完成,按下这个组合键时,系统 <BR>象当前的前台程序发送SIGTSTP信号,于是当前程序被阻止,你可以在这个期间进行其他 <BR>工作,例如,在前面的例子中显示的被阻止的vi就是这样一个程序,用jobs命令可以显 <BR>示当前被^Z挂起的程序: <BR> <BR> [openlab]# jobs <BR> <BR> [1]+ Stopped vi <BR> <BR> 最前面的号码是作业号,在挂起这个程序之后,你可以用fg命令将它重新投入前台运 <BR>行,或者用bg命令将它放到后台去执行。 <BR> <BR> 语法是 <BR> <BR> fg [作业号] <BR> <BR> bg [作业号] <BR> <BR> 省略作业号则执行最近被阻止的作业。 <BR> <BR> 当一个进程的父进程被撤销时,它通常会接受到撤销信号,从而它也会退出。 <BR> <BR> 另外一个常用的指令是&,它通常用于避免程序截获前台输入,例如,在xterm下,直 <BR>接执行netscape & 将启动netscape 程序,在netscape退出前,xterm只能等待。相反, <BR>netscape &指令启动netscape,同时xterm仍然可以处理前台命令。 <BR> <BR> 2.5.2 forks和exec <BR> <BR> forks是UNIX中被程序员熟知的功能之一。简单地讲,forks创造一个新的进程。 <BR> <BR> 实际上,forks是一个进程用来克隆自身的方法,某个进程调用forks将在内存中开设 <BR>一个自身的拷贝,即建立一个与自身几乎完全相同的进程。执行forks的进程称为父进程 <BR>,而克隆出的进程称为子进程。两者只有非常小的区别:两个进程的pid号不同;新进程 <BR>要建立自己的一些资源。 <BR> <BR> 实际上,整个UNIX的进程创建机制都是基于forks的。执行一个新的程序在UNIX中有一 <BR>个专门的功能组,称为exec,它包含彼此差不多的一些函数族,如execl,execv等等,功 <BR>能上也相似,都是去执行另外一个程序。但是,UNIX的exec函数被设计为被执行的程序 <BR>接管原来程序的全部资源,因此当被执行的程序结束以后,执行程序也就消亡了。显然 <BR>,这不是我们想要的,所以,UNIX/Linux在准备启动一个新的程序时,负责启动的程序 <BR>首先调用forks产生出一个新的进程,在这个过程中它使用forks的一个功能,即forks函 <BR>数自动区分是原始进程还是被forks出来的进程,如果是子进程则调用exec来执行所要调 <BR>用的程序。 <BR> <BR> 一个主进程可以forks出多个子进程,当然,forks越多,就消耗越多的资源,有时这 <BR>可能是很讨厌的,因此,在大部分Linux系统上限制每个进程只能forks出有限的进程数 <BR>,缺省下这个数字是256。因为许多服务器守护进程都依赖于forks,所以这个限制经常 <BR>是服务器噩梦的来源。如果你的网络负担非常沉重,你可能必须手工调节这个数字把它 <BR>加大到一个合理的值。(不过,也许使用更强大的系统是更合适的解决方法?) <BR> <BR> 要察看当前的 forks极限,使用ulimit命令: <BR> <BR> [wanghy@openlab wanghy]$ ulimit -u <BR> <BR> 256 <BR> <BR> 如果要设置forks极限,使用带参数的ulimit指令: <BR> <BR> ulimit –u 512 <BR> <BR> 这个命令将forks极限设置为512。 <BR> <BR> ulimit –u unlimited <BR> <BR> 这个命令取消对forks的限制。 <BR> <BR> 另一个问题是进程的优先级。内核调度任务时,优先级越高的任务能得到越高的CPU使 <BR>用率。一般情况下,内核会自动安排进程的优先级,而且这种普通的进程优先级机制已 <BR>经完全够用,然而,在某些极端的情况下,你可能想让某些任务以尽可能高的优先级执 <BR>行。 <BR> <BR> 强行指定某个进程的优先级是不可能的,但是你可以在一定的范围内让某个任务以尽 <BR>可能高的优先级运行,这可以用nice命令实现: <BR> <BR> nice –n -15 sh <BR> <BR> 这个命令让你以一个很高的优先级执行一个新的shell。-n后面的数用来标志你对这个 <BR>进程的期待值,这个数越小,进程的优先级越高,范围是从-20到19。 <BR> <BR> 启动的进程仍然可以用renice命令修改期待值,例如: <BR> <BR> renice –20 1553 <BR> <BR> 将pid为1553的程序的优先级提升到最高。 <BR> <BR> 2.5.3 守护和服务器守护程序 <BR> <BR> 守护程序就是一个在后台跑的程序,它通常用来执行一些系统相关的任务。大部分守护 <BR>进程都是在系统启动是投入运行,随时等待呼叫。但是守护程序也可以设置为手动启动 <BR>和停止。 <BR> <BR> 最基本的守护程序是init程序,当系统启动后它就开始运行,实际上除了内核产生的 <BR>进程以外所有的进程都是init直接间接地forks出来的。另外两个几乎一切UNIX都必须提 <BR>供的守护程序是inetd和crond,crond用来设置在某个特定的时间执行特定的工作(例如 <BR>:在每星期六晚上10:00开始整理硬盘)。 <BR> <BR> inetd是一个用来管理许多存取不太频繁的服务进程的守护程序,它在有任务时启动 <BR>对应的服务进程并且在网络客户程序和服务进程之间执行翻译,通过inetd启动的服务器 <BR>进程可以不理会复杂的BSD网络编程接口,inetd把通过网络的通信翻译成普通的文件读 <BR>写操作,使得编程变得简单,但是相应地,inetd的效能不是很好,因此重负荷的应用通 <BR>常用独立的守护进程实现。 <BR> <BR> 大部分独立的网络服务被实现为服务器守护程序,它们可以被绑定在某一个端口上, <BR>在后台接受客户的请求,许多这样的守护程序使用forks机制来完成工作,例如sendmai <BR>l。sendmail监听向25端口的请求,当接受到一个这样的请求时,它forks出一个自身的 <BR>拷贝,将连结请求交给这个子进程,然后它自己又可以在25端口上继续监听。 <BR> <BR> 由于forks的问题,个别服务器守护程序会在内存中产生多个子进程,例如httpd程序 <BR>,在一台负担很重的机器上,它可以产生出几百个子进程,而只有第一个进程是真正的 <BR>控制进程。要找到这样的进程当然可以用more和grep命令仔细寻找,但是Linux系统中提 <BR>供别的方法,前面讲到的killall是一个可行的方案,另外一个方法包含在/var/run目录 <BR>中,其中会以xxxx.pid的形式包含了守护进程启动时(第一个)的pid,其命名方法就是 <BR>守护进程的名字(如果是在inetd.conf中启动的守护进程则由inetd程序命名),格式就 <BR>是一个简单的文本文件,例如: <BR> <BR> [wanghy@mail run]$ cat /var/run/httpd.pid <BR> <BR> 392 <BR> <BR> [wanghy@mail run]$ ps ax | grep httpd | more <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -