1、守护进程

  守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。所有的守护进程都没有控制终端,其终端名设置为问号。

2、编程规则

  1)首先调用umask函数将文件模式创建屏蔽字设置为一个已知值,通常是0;

  umask函数为进程设置文件模式创建屏蔽字,并返回以前的值。umask也是shell命令,功能和umask函数一样。

 #include <sys/stat.h>

 mode_t umask(mode_t mask);

  在进程创建一个新的文件或目录时,如调用open函数创建一个新文件,新文件的实际存取权限是mode与umask按照  mode&~umask运算以后的结果。umask函数用来修改进程的umask。

  首先看一下umask命令的作用:

    首先查看一下当前的umask为022,用vi创建一个umask_3.c,查看该文件的权限为644,修改umask为0,vi创建umask_4.c,查看该文件的权限为666。

     

  umask函数的使用:

    实现函数,首先修改当前进程umask为0.创建fan_test1文件,然后修改umask为006,创建文件fan_test2,输出结果如下图

 #include <stdio.h>
#include <sys/stat.h> int main()
{
umask();
if (creat("fan_test1",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < )
printf("error creat\n");
umask(S_IROTH|S_IWOTH);
if (creat("fan_test2",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < )
printf("error creat\n");
return ;
}

    

  2)调用fork,然后是父进程exit。创建守护进程最关键的一步是调用setsid函数创建一个新的会话(会话是一个或多个进程组的集合),使守护进程成为新会话的首进程,并成为新进程组的组长,失去当前的控制终端,成为一个没有控制终端的进程。而调用函数setsid()之前,要保证当前进程不是进程组的组长,否则该函数返回-1;要保证当前进程不是进程组的组长,就要调用fork,父进程退出;fork创建的子进程和父进程在同一个进程组中,进程组的组长必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,fork之后调用setsid就没有问题了;

  3)调用setsid()函数创建一个新的会话:

       (1) 该进程变成新会话首进程,会话首进程通常是创建该会话的进程,该进程是新会话中的唯一的进程。
       (2) 该进程成为一个新进程组的组长进程,新进程组ID就是调用进程的ID。
       (3) 该进程没有控制终端,如果在调用setsid之前该进程有一个控制终端,那么这种联系将被中断。

  4)将当前的工作目录更改为根目录。如果守护进程所在的目录为一个挂载的文件系统,那么该文件系统就不能被卸载;另外如果守护进程所在的目录不是根目录,启动守护进程之后,当前工作目录所在的文件夹将不能删除;调用函数chdir("/");

  5)关闭打开的文件描述符;子进程有可能从父进程继承了一些打开的文件,这些文件可能守护进程将不再使用,但这些文件描述符依然消耗系统资源,也有可能导致相关的文件系统无法被卸载。

  关闭文件描述符的方法:

 方法1:
#include <sys/resource.h> struct rlimit rl; 6 if(getrlimit(RLIMIT_NOFILE, &rl) < )
7 {
perror("getrlimit(RLIMIT_NOFILE, &rl)");
return -;
10 }
11 if(rl.rlim_max == RLIM_INFINITY)
12 {
13 rl.rlim_max = ;
14 }
15 for(i = ; i < rlim_max; i++)
{
close(i);
}
方法2:
max_fd = sysconf(_SC_OPEN_MAX);
for(i = ; i < max_fd; i++)
{
close(i);
}

  6)守护进程打开/dev/null使其具有文件描述符0、1和2,也就是将0、1、2的文件描述符都指向/dev/null; 

 /*attach file descriptions 0,1 and  2 to /dev/null*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup();
fd2 = dup();

  为什么会有这一步操作,守护进程已经脱离终端了,为什么还要将文件描述符0、1、2重定向到/dev/null呢,并且前面已经有了关闭所有文件描述符的操作,文件描述符已经关闭了,在此处为什么还要再打开,两者不是冲突了么?

  7)再次调用fork,使父进程退出;第一次fork()后的子进程已经成为会话组的组长,有权利再调出一个终端,如果出现此情况,则未达到完全脱离终端的目的,此时再调用fork并退出父进程,使得此时的子进程成为完全的后台进程,独立于任何的终端,在第二次fork之前通常会忽略SIGHUP信号,这是因为会话首进程退出时会给该会话中的前台进程组(当打开控制终端后,就有一个前台进程组)的所有进程发送SIGHUP信号,而信号的默认处理函数通常是进程终止,因此需要对信号进程屏蔽处理

实现一个守护进程:

 #include <stdio.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>
void daemonize(void)
{
struct rlimit rl;
pid_t pid;
struct sigaction sa;
int i;
umask();
if (getrlimit(RLIMIT_NOFILE, &rl) < ) {
printf("error getrlimit\n");
exit();
}
if ((pid = fork()) < ) {
printf("error fork\n");
exit();
} else if (pid != ) {
exit();
}
setsid();
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = ;
if (sigaction(SIGHUP, &sa, NULL) < ) {
printf("error sigaction\n");
exit();
}
if (chdir("/") < ) {
printf("error chdir\n");
exit();
}
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = ;
for (i = ; i < rl.rlim_max; i++)
close(i); if ((pid = fork()) < ) {
printf("error fork\n");
exit();
} else if (pid != ) {
exit();
} } int main()
{
daemonize();
while() {
printf("111111111111111\n");
sleep();
} }

  

多进程编程之守护进程Daemonize的更多相关文章

  1. Unix环境高级编程(十三)守护进程

    守护进程也称为精灵进程是一种生存期较长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.unix系统有很多守护进程,大多数 ...

  2. python 之 并发编程(守护进程、互斥锁、IPC通信机制)

    9.5 守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就立即终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic process ...

  3. Linux编程实现守护进程

    Linux 守护程序 守护进程(Daemon)它是在一个特定的过程的背景进行.它独立于控制终端的和周期性地执行某些任务或待某些事件.是一种非常实用的进程. Linux的大多数server就是用守护进程 ...

  4. Unix环境高级编程:守护进程

    参考 Unix环境高级编程,第9,13章 介绍 守护进程就是Linux中使用ps aux那些一般以d结尾的程序,比如rsyslogd,sshd等,为daemon简称.他们是长期在后台执行的随终端关闭而 ...

  5. 高级UNIX环境编程13 守护进程

    linux下,keventd守护进程为内核中运行的执行的函数提供进程上下文 bdflush,kupdated将高速缓存中的数据冲洗到磁盘上

  6. Linux系统编程之--守护进程的创建和详解【转】

    本文转载自:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终 ...

  7. python并发编程之守护进程、互斥锁以及生产者和消费者模型

    一.守护进程 主进程创建守护进程 守护进程其实就是'子进程' 一.守护进程内无法在开启子进程,否则会报错二.进程之间代码是相互独立的,主进程代码运行完毕,守护进程也会随机结束 守护进程简单实例: fr ...

  8. [linux] C语言Linux系统编程-做成守护进程

    守护进程: 必须是init进程的子进程,运行在后台,不与任何控制终端相关联. 通过以下步骤成为守护进程 1.调用fork()创建出来一个新的进程,这个新进程会是将来的守护进程 2.在新守护进程的父进程 ...

  9. linux系统编程:守护进程详解及创建,daemon()使用

    一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...

随机推荐

  1. node的 node-sass@^4.11.0 出现:npm: no such file or directory, scandir '.../node_modules/node-sass/vendor'

    解决办法: 查看node_modules文件夹,发现,并无vender 文件夹.如下图: 2.  在 node_modules/node-sass 下创建 vendor 文件夹 3.  最后运行: n ...

  2. 【Unity Shader】(十) ------ UV动画原理及简易实现

    笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...

  3. Linux命令的那些事(一)

    回顾一下前文,三大主流操作系统 windows做的最好(更准确最早做图形化界面是windows)其实是图形化界面占有90%的市场份额(PC(个人电脑)机的市场)但是现在发展图形界面做的较好其实Unix ...

  4. SQL知识点脑图(一张图总结SQL)

    sql语言的分类DDL:create drop alter DML:insert delete update DCL:rollback grant revoke commit 概要,主外键,视图,索引 ...

  5. 前端常见算法面试题之 - 从尾到头打印链表[JavaScript解法]

    题目描述 输入一个链表的头结点,从尾到头反过来打印出每个结点的值 实现思路 前端工程师看到这个题目,直接想到的就是,写个while循环来遍历链表,在循环中把节点的值存储在数组中,最后在把数组倒序后,遍 ...

  6. oozie捕获标准输出&异常capture-output

    对于普通的java-action或者shell-action 都是支持的只要标准输出是"k1=v1"这中格式的就行: 现用test.py进行测试: ##test.py #! /op ...

  7. php从入门到放弃系列-01.php环境的搭建

    php从入门到放弃系列-01.php环境的搭建 一.为什么要学习php 1.php语言适用于中小型网站的快速开发: 2.并且有非常成熟的开源框架,例如yii,thinkphp等: 3.几乎全部的CMS ...

  8. 高可用OpenStack(Queen版)集群-1. 集群环境

    参考文档: Install-guide:https://docs.openstack.org/install-guide/ OpenStack High Availability Guide:http ...

  9. 深度学习中数据的augmentation

    为了提高模型的泛化能力,同时也为了增大数据集,我们往往需要对数据进行augmentation,在这篇博客中,将总结一下可以对数据进行的augmentation. 1.颜色数据增强,对图像亮度.饱和度. ...

  10. 查看linux端口对应的进程id

    例如:查看占用4040端口的进程 ss -lptn 'sport = :4040'