关于精灵进程的一些思考和代码片段



设置精灵进程


static void set_daemon(void)

{

       pit_t pid;

       int     fd;

       pid = fork();

       if(pid < 0)

      {

扫描二维码关注公众号,回复: 4722966 查看本文章

            log_error("Set daemon error!);

            exit(-1);

      }

     else if( pid > 0)

     {

             exit(0);

      }

     fd  = open("/dev/null".O_RDWR);

     /* we want close stdin stdou*/

    {

          close(0);

          close(1);

          dup(fd);

          dup(fd);

          close(fd);

     }    

    setsid();

    pid = fork();

    if( pid<0)

   {

       log_error("Set: daemon error");

       exit(-1);

   }

    else if(pid > 0)

    {

         exit(0);

    }

}


其中,最重要的一个函数调用是setsid,目的是创建一个新对话期。使调用进程:

(a)成为新对话期的首进程

(b)成为一个新进程组的首进程

(c)没有控制终端
   这里面有三个概念:进程组、会话期与控制终端,下面分别阐述。


进程组:

进程组的概念是因管道符而生。
用管道符连接的进程都在同一个进程组里,例如:
ps -xj | cat1 | cat2
如果想杀掉所有相关进程,就必须引入进程组的概念。以下是kill调用的方法:
int kill(pid_t pid, int signo);
pid==0 将信号发送给其进程组I D等于发送进程的进程组I D,而且发送进程有许可权向
其发送信号的所有进程。
pid<0 将信号发送给其进程组I D等于p i d绝对值,而且发送进程有许可权向其发送信号
的所有进程。


引入会话期与控制终端的意义:
会话期与控制终端的概念是因后台进程而生。
例如:tail -f log.file &
该进程不接收退出信号(ctrl + C),并且在用户退出登陆后依然存在,这种进程我们称为后台进程,后台进程的实现需要引入会话期与控制终端的概念。

以下是会话期和控制终端的描述:
1.对话期可以包括多个进程组。
2.一个对话期可以有一个单独的控制终端( controlling terminal)。这通常是我们在其上登录的终端设备(终端登录情况)或伪终端设备(网络登录情况)。
3.一个对话期中的几个进程组可被分成一个前台进程组( foreground process group)以及一个或几个后台进程组(background process group)
如果一个对话期有一个控制终端,则它有一个前台进程组,其他进程组则为后台进程组。
4.无论何时键入中断键(常常是D E L E T E或C t r l - C)或退出键(常常是C t r l - \),就会造成将中断信号或退出信号送至前台进程组的所有进程。
 
setsid的用法
进程调用setsid函数就可建立一个新对话期。
如果调用此函数的进程不是一个进程组的组长,则此函数创建一个新对话期,结果为:
(1) 此进程变成该新对话期的对话期首进程(session leader,对话期首进程是创建该对话期的进程)。此进程是该新对话期中的唯一进程。
(2) 此进程成为一个新进程组的组长进程。新进程组id是此调用进程的进程ID。
(3) 此进程没有控制终端(下一节讨论控制终端)。如果在调用setsid之前此进程有一个控
制终端,那么这种联系也被解除。
如果此调用进程已经是一个进程组的组长,则此函数返回出错。为了保证不处于这种情况,
通常先调用fork,然后使其父进程终止,而子进程则继续。因为子进程继承了父进程的进程组ID,而其进程ID则是新分配的,两者不可能相等,所以这就保证了子进程不是一个进程组的组长。


1、首先调用fork,然后使父进程exit.
2、调用setsid以创建一个新的会话。
3、调用chdir将工作目录改为根目录。
4、将文件方式创建屏蔽字设为0.(umask(0);)
5、关闭不需要的文件描述字。

精灵进程退出处理


当用户需要外部停止守护进程运行时,往往会使用 kill命令停止该守护进程。所以,守护进程中需要

编码来实现kill发出的signal信号处理,达到进程的正常退出


signal(SIGTERM, sigterm_handler);
void sigterm_handler(int arg)
{
_running = 0;
}
===============================
这样,一个简单的守护进程就建立起来了。
实现守护进程的完整实例(每隔10s在/tmp/dameon.log中写入一句话):






猜你喜欢

转载自blog.csdn.net/liulong1010/article/details/44701351