进程编程中的守护进程

进程编程中的守护进程

概念

  • 守护进程是在后台运行不受控端控制的进程,通常情况下守护进程在系统启动时自动运行
  • 守护进程的名称通常以d结尾,比如sshd、xinetd、crond等

可以利用killall 进程名字 来杀一族进程,命令很爽。。。。不需要 kill -9 pid

创建步骤


  1. 调用fork(),创建新进程,它会是将来的守护进程
  2. 在父进程中调用exit,保证子进程不是进程组组长
  3. 调用setsid创建新的会话期
  4. 将当前目录改为根目录 (如果把当前目录作为守护进程的目录,当前目录不能被卸载,它作为守护进程的工作目录了。为了避免需要卸载当前目录引起错误,所以需要修改当前的工作目录)。
  5. 将标准输入、标准输出、标准错误重定向到/dev/null

因为”后台任务”的标准 I/O 继承自当前 session,创建新的会话期以后并没有改变这一点。一旦”后台任务”读写标准 I/O,就会发现它已经不存在了(属于之前的会话期),所以就报错终止执行。
为了解决这个问题,需要对”后台任务”的标准 I/O 进行重定向。

API

  • 函数原型:int daemon(int nochdir, int noclose);
  • 功能:创建一个守护进程
  • 参数:
    • nochdir:=0将当前目录更改至“/”
    • noclose:=0将标准输入、标准输出、标准错误重定向至“/dev/null”

使用该函数不需要按照上述的五步骤去创建守护进程,C库函数帮我们做了大量的工作!

  • 函数原型:pid_t setsid(void);
  • 功能:Setsid创建一个新的会话;调用者进程会是这个会话期唯一的一个进程,是唯一组的组长;调用者进程id是组id,也是会话期的id。不能用进程组组长去调用setsid函数
  • 返回值:成功返回调用者进程的新会话期的ID/进程组ID,失败返回-1

  • 运行ps -ef命令

root       2445   1208  0 19:49 ?        00:00:00 sshd: zhenjunliu [priv]
zhenjun+   2500   2445  0 19:49 ?        00:00:00 sshd: zhenjunliu@notty
zhenjun+   2503   2500  0 19:49 ?        00:00:00 /usr/lib/openssh/sftp-server
zhenjun+   2522   2441  0 19:49 ?        00:00:00 sshd: zhenjunliu@pts/5
zhenjun+   2523   2522  0 19:49 pts/5    00:00:00 -bash
root       5625      2  0 22:05 ?        00:00:01 [kworker/0:2]
root       5988      2  0 22:21 ?        00:00:00 [kworker/3:0]

有的进程有tty,有的进程没有tty。带问号的是守护进程。

会话期和进程组

  • 会话期:是一个或者多个进程组的集合,通常一个会话期开始于用户登录,终止于用户退出。在此期间,该用户运行的所有进程都属于这个会话期。
  • 一个会话期里面可能有多个进程,这些进程就是一个进程组!每个组有一个组长!组长的PID就是进程组ID。

示例代码

#include <sys/types.h>
#include <unistd.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <signal.h>
#include <errno.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

int my_daemon(int nochdir, int noclose)
{
    int i = 0;
    pid_t pid;

    pid = fork();
    if (pid == -1)
    {
        perror("fork err");
        exit(0);
    }


    if (pid > 0)
    {
        exit(0);
    }
    printf("pid:%d \n", getpid());
    pid = setsid();
    if (pid == -1)
    {
        perror("fork err");
        exit(0);
    }

    if (nochdir != 0)
        chdir("/");

    if (noclose != 0)
    {
        for (i=0; i<3; i++)
        {
            close(i);
        }
    }

    open("/dev/null", O_RDWR); 
    dup(0);
    dup(1);


    while(1)
    {
        sleep(1);
    }

    printf("hello\n");
    return 0;
}


int main()
{
        my_daemon(1, 1);
        return 0;
}

关于守护进程的更多了解参见:http://blog.chinaunix.net/uid-20937170-id-5748313.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值