C++守护进程编程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/88930723

一 点睛

Linux Deamon守护进程是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或者等待处理某些事件的发生。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。

守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。

一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。

守护进程的名称通常以d结尾,比如sshd、xinetd(管理网络相关服务)、crond等。

1 守护进程特点

  • 守护进程都具有超级用户的权限。

  • 守护进程的父进程是init进程。

  • 守护进程都不用控制终端,其TTY列以“?”表示,TPGID为-1.

  • 守护进程都是各自进程组合会话过程的唯一进程。

2 查看守护进程

[root@localhost 5.10]# ps axj
PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0   0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2     3     0     0 ?           -1 S        0   0:00 [ksoftirqd/0]
    2     5     0     0 ?           -1 S<       0   0:00 [kworker/0:0H]
    2     6     0     0 ?           -1 S        0   0:00 [kworker/u2:0]
    2     7     0     0 ?           -1 S        0   0:00 [migration/0]
    2     8     0     0 ?           -1 S        0   0:00 [rcu_bh]
    2     9     0     0 ?           -1 R        0   0:00 [rcu_sched]
    2    10     0     0 ?           -1 S        0   0:00 [watchdog/0]
    2    12     0     0 ?           -1 S        0   0:00 [kdevtmpfs]
    2    13     0     0 ?           -1 S<       0   0:00 [netns]
    2    14     0     0 ?           -1 S        0   0:00 [khungtaskd]
    2    15     0     0 ?           -1 S<       0   0:00 [writeback]
    2    16     0     0 ?           -1 S<       0   0:00 [kintegrityd]
    2    17     0     0 ?           -1 S<       0   0:00 [bioset]
    2    18     0     0 ?           -1 S<       0   0:00 [kblockd]
    2    19     0     0 ?           -1 S<       0   0:00 [md]
    2    20     0     0 ?           -1 R        0   0:00 [kworker/0:1]
    2    25     0     0 ?           -1 S        0   0:00 [kswapd0]
  ......
  855   969   969   969 ?           -1 Ss       0   0:00 sshd: root@pts/0
  969   973   973   973 pts/0     1004 Ss       0   0:00 -bash
    2  1002     0     0 ?           -1 S        0   0:00 [kworker/0:2]
    2  1003     0     0 ?           -1 S        0   0:00 [kworker/0:0]
  973  1004  1004   973 pts/0     1004 R+       0   0:00 ps axj

从上面结果看出,TTY表示控制终端,可以看到这几个守护进程的控制终端为"?",意思是这几个守护进程没有控制终端。UID为0,表示进程的启动者是超级进程。

3 守护进程的启动方式

  • 在系统启动时由启动脚本启动,这些启动脚本通常放在/etc/rc.d目录下。

  • 利用inetd超级服务器启动,如telnet等。

  • 由cron定时启动,在终端用nohub启动的进程也是守护进程。

4 编写守护进程的步骤

  • 创建子进程,父进程退出

  • 在子进程中创建新对话

  • 改变当前目录为根目录

  • 重设文件权限掩码

  • 关闭文件描述符

  • 守护进程退出处理

二 实战——隔10秒在/tmp/dameon.log中写入一句话

1 编码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/stat.h>

#define MAXFILE 65535

volatile sig_atomic_t _running = 1;

void sigterm_handler(int arg)
{
    _running = 0;
}

int main()
{
    pid_t pc;
    int i, fd, len;
    char *buf = "this is a Dameon\n";
    len = strlen(buf);
    pc = fork(); //第一步
    if(pc < 0)                                                   
    {
        printf("error fork\n");
        exit(1);
    }
    else if(pc > 0)
        exit(0);

    setsid(); //第二步
    chdir("/"); //第三步
    umask(0); //第四步
    for(i = 0 ; i < MAXFILE ; i++) //第五步
        close(i);
    signal(SIGTERM, sigterm_handler);
    while(_running)
    {
        if((fd = open("/tmp/dameon.log", O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0) \
        {
            perror("open");
            exit(1);
        }
        write(fd, buf, len + 1);
        close(fd);
        usleep(10 * 1000); //10毫秒
    }

}

2 编译运行

[root@localhost 5.11]# g++ -o test test.cpp
[root@localhost 5.11]# ll
total 16
-rwxr-xr-x. 1 root root 9208 Mar 31 16:01 test
-rw-r--r--. 1 root root  978 Mar 24 13:11 test.cpp
[root@localhost 5.11]# ./test

3 查看

[root@localhost 5.11]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root      1042     1  0 16:18 ?        00:00:01 ./test
root      1045     2  0 16:20 ?        00:00:00 [kworker/0:3]
root      1047   973  0 16:21 pts/0    00:00:00 ps -ef
[root@localhost 5.11]# vi /tmp/dameon.log

this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon
^@this is a Dameon

4 关闭

[root@localhost 5.11]# kill -9 1042

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/88930723