|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
每一个开发团队都对他的发行版做过测试后放出的.那些国际知名的大品牌更是如此。
保卫历程(Daemon)是运转在背景的一种特别历程。它自力于把持终端而且周期性地实行某种义务或守候- 处置某些产生的事务。保卫历程是一种很有效的历程。Linux的年夜多半服务器就是用保卫历程完成的。好比,Internet服务器inetd,Web服务器httpd等。同时,保卫历程完成很多体系义务。好比,功课计划历程crond,打印历程lpd等。 保卫历程的编程自己其实不庞大,庞大的是各类版本的Unix的完成机制不尽不异,形成分歧Unix情况下保卫历程的编程划定规矩其实不分歧。必要注重,照搬某些书上的划定规矩(出格是BSD4.3和低版本的SystemV)到Linux会呈现毛病的。上面分离一些先辈的文档和本人的例子说说保卫历程的编程。.基础观点.历程.每一个历程都有一个父历程.当子历程停止时,父历程会失掉关照并能获得子历程的加入形态。.历程组.每一个历程也属于一个历程组.每一个历程主都有一个历程组号,该号即是该历程组组长的PID号.一个历程只能为它本人或子历程设置历程组ID号.会话期.对话期(session)是一个或多个历程组的汇合。.setsid()函数能够创建一个对话期:假如,挪用setsid的历程不是一个历程组的组长,此函数创立一个新的会话期。(1)此历程酿成该对话期的首历程(2)此历程酿成一个新历程组的组上进程。(3)此历程没有把持终端,假如在挪用setsid前,该历程有把持终端,那末与该终真个接洽被排除。假如该历程是一个历程组的组长,此函数前往毛病。(4)为了包管这一点,我们先挪用fork()然后exit(),此时只要子历程在运转,子历程承继了父历程的历程组ID,可是历程PID倒是新分派的,以是不成能是新会话的历程组的PID。从而包管了这一点。if((pid=fork())>0)//parentexit(0);elseif(pid==0){//th1childsetsid();//th1是成为会话期组长if(fork()==0){//th2不会是会话期组长(酿成孤儿历程组)...}}一.保卫历程及其特征(1)保卫历程最主要的特征是背景运转。在这一点上DOS下的常驻内存程序TSR与之类似。(2)其次,保卫历程必需与其运转前的情况断绝开来。这些情况包含未封闭的文件形貌符,把持终端,会话和历程组,事情目次和文件创立掩模等。这些情况一般是保卫历程从实行它的父历程(出格是shell)中承继上去的。(3)最初,保卫历程的启动体例有其特别的地方。它能够在Linux体系启动时从启动剧本/etc/rc.d中启动,能够由功课计划历程crond启动,还能够由用户终端(一般是shell)实行。 总之,除开这些特别性之外,保卫历程与一般历程基础上没有甚么区分。因而,编写保卫历程实践上是把一个一般历程依照上述的保卫历程的特征改革成为保卫历程。二.保卫历程的编程要点(来自UEAP) 后面讲过,分歧Unix情况下保卫历程的编程划定规矩其实不分歧。所幸的是保卫历程的编程准绳实在都一样,区分在于详细的完成细节分歧。这个准绳就是要满意保卫历程的特征。同时,Linux是基于SyetemV的SVR4并遵守Posix尺度,完成起来与BSD4比拟更便利。编程要点以下;1.在背景运转。 为制止挂起把持终端将Daemon放进背景实行。办法是在历程中挪用fork使父历程停止,让Daemon在子历程中背景实行。if(pid=fork())exit(0);//是父历程,停止父历程,子历程持续2.离开把持终端,登录会话和历程组 历程属于一个历程组,历程组号(GID)就是历程组长的历程号(PID)。登录会话能够包括多个历程组。这些历程组共享一个把持终端。这个把持终端一般是创立历程的登录终端。把持终端,登录会话和历程组一般是从父历程承继上去的。我们的目标就是要挣脱它们,使之不受它们的影响。办法是在第1点的基本上,挪用setsid()使历程成为会话组长:setsid(); 申明:当历程是会话组长时setsid()挪用失利。但第一点已包管历程不是会话组长。setsid()挪用乐成后,历程成为新的会话组长和新的历程组长,并与本来的登录会话和历程组离开。因为会话历程对把持终真个独有性,历程同时与把持终端离开。3.克制历程从头翻开把持终端 如今,历程已成为无终真个会话组长。但它能够从头请求翻开一个把持终端。能够经由过程使历程不再成为会话组长来克制历程从头翻开把持终端:if(pid=fork())exit(0);//停止第一子历程,第二子历程持续(第二子历程不再是会话组长)4.封闭翻开的文件形貌符 历程从创立它的父历程那边承继了翻开的文件形貌符。如不封闭,将会华侈体系资本,形成历程地点的文件体系没法卸下和引发没法意料的毛病。按以下办法封闭它们:for(i=0;i封闭翻开的文件形貌符close(i);>5.改动以后事情目次 历程举动时,其事情目次地点的文件体系不克不及卸下。一样平常必要将事情目次改动到根目次。关于必要转储中心,写运转日记的历程将事情目次改动到特定目次如/tmpchdir("/")6.重设文件创立掩模 历程从创立它的父历程那边承继了文件创立掩模。它大概修正保卫历程所创立的文件的存取位。为避免这一点,将文件创立掩模扫除:umask(0);7.处置SIGCHLD旌旗灯号 处置SIGCHLD旌旗灯号并非必需的。但关于某些历程,出格是服务器历程常常在哀求到来时天生子历程处置哀求。假如父历程不守候子历程停止,子历程将成为僵尸历程(zombie)从而占用体系资本。假如父历程守候子历程停止,将增添父历程的包袱,影响服务器历程的并发功能。在Linux下能够复杂地将SIGCHLD旌旗灯号的操纵设为SIG_IGN。signal(SIGCHLD,SIG_IGN); 如许,内核在子历程停止时不会发生僵尸历程。这一点与BSD4分歧,BSD4下必需显式守候子历程停止才干开释僵尸历程。三.保卫历程实例 保卫历程实例包含两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目次中的日记test.log呈报运转形态。初始化程序中的init_daemon函数卖力天生保卫历程。读者能够使用init_daemon函数天生本人的保卫历程。1.init.c清单#include<unistd.h>#include<signal.h>#include<sys/param.h>#include<sys/types.h>#include<sys/stat.h>voidinit_daemon(void){intpid;inti;if(pid=fork())exit(0);//是父历程,停止父历程elseif(pid<0)exit(1);//fork失利,加入//是第一子历程,背景持续实行setsid();//第一子历程成为新的会话组长和历程组长//并与把持终端分别if(pid=fork())exit(0);//是第一子历程,停止第一子历程elseif(pid<0)exit(1);//fork失利,加入//是第二子历程,持续//第二子历程不再是会话组长for(i=0;i<NOFILE;++i)//封闭翻开的文件形貌符close(i);chdir("/tmp");//改动事情目次到/tmpumask(0);//重设文件创立掩模return;}2.test.c清单#include<stdio.h>#include<time.h>voidinit_daemon(void);//保卫历程初始化函数main(){FILE*fp;time_tt;init_daemon();//初始化为Daemonwhile(1)//每隔一分钟向test.log呈报运转形态{sleep(60);//就寝一分钟if((fp=fopen("test.log","a"))>=0){t=time(0);fprintf(fp,"Imhereat%sn",asctime(localtime(&t)));fclose(fp);}}}以上程序在RedHatLinux6.0下编译经由过程。步骤以下:编译:gcc-g-otestinit.ctest.c实行:./test检察历程:ps-ef申明:在体系挪用库中有一个库函数能够间接使一个历程酿成保卫历程,#include<unistd.h>intdaemon(intnochdir,intnoclose);
复制代码 RedHatCentOS等等.学习linux不是逛自由市场,选定版本就要静下心来学习.不要今天换版本明天要升级.这样对你没有好处。 |
|