今天继续学习系统编程,学习的主题还是进程,今天主要讨论的是守护进程相关的概念,开始进入正题:

什么是守护进程:
 
 
 
守护进程的创建步骤:
在描述它之前,首先得先了解两个概念:进程组、会话期:
 
而它里面有bash shell进程组,里面只有bash进程:
 
这时,当我们在shell命令行中敲入如下命令:
这时,会话期中又会多出一个进程组,如下:
而一个会话期,实际上就对应一个终端,当我们打开多个虚拟终端时,可以用tty来查看终端数:
守护进程是跟控制终端无关的,并且是在后台执行的,如果想让我们在shell中启动的进程变成守护进程,则应该将它放到会话期当中:
那这时,我们需要一个创建新的会话期的函数,实际上是系统函数,它为setsid(),通过man来查看一下它的说明:
这就意味着,我们在创建一个新的会话期之前,需要准备一个进程,保证该进程不是一个进程组组长,那如何保证呢?由于我们运行的shell命令的父进程可能是进程组组长,所以需要让父进程退出,这样就可以保证fork出来的子进程不是进程组组长,从而可以创建一个新的会话期了,总结一下上面说的流程:
按照上面的步骤下面以具体代码来实现一个守护进程:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() int setup_daemon(void); int main(int argc, char *argv[])
{
return ;
} int setup_daemon(void)
{
pid_t pid;
pid = fork();
if (pid == -)
ERR_EXIT("fork error"); if (pid > )//将父进程退出,保证子进程不是进程组组长
exit(EXIT_SUCCESS); setsid();//如果走到这,代表是子进程,由于它不是一个进程组组长,所以可以创建一个新的会话期
return ; }

当我们用setsid()创建一个新的会话期之后,会有一个什么样的影响呢,还是接着看它的说明介绍:

也就是如下图所示:

其实上面的程序就已经实现了一个守护进程,我们调用一下运行看下:

编译运行:

我们来查看下进程:

守护进程通常是在系统运行而运行的,通常将当前目录改为根目录,因为有可能守护进程是在某个shell提示符下运行的, 那么当前目录就是shell提示符所在的目的, 就拿我们创建的这个守护进程而言,它的当前目录为:

这样,系统管理员就无法umount这个目录,因为守护进程是学期在后期运行的,这个目录不应该作为它的环境,所以这就产生了创建守护进程的第四个步骤:

修改代码:

最后还有一个步骤:

说明:/dev/null表示空设备,这里就是把日志记录到空设备里,就是不记录日志。】

怎么做呢?先看代码:

这时再运行,如果我们往屏幕输出内容,这时是看不到内容的,因为已经将标准输出重定向了空设备:

说明:关于dup的知识,可参考博文:http://www.cnblogs.com/webor2006/p/3498443.html

daemon:
实际上linux上已经有现成的方法可以创建一个守护进程了,如下:
 
我们使用一下它:
在运行它之前,我们来看下现在应该有几个守护进程了:
先将其都杀掉,以便来观察调用系统的创建守护进程是否成功:
这时,再运行:
对于系统的这个函数,都是传递的0,如果传递1会怎样呢?
编译运行:
实际上,对于我们写的守护进程,也可以模拟成跟系统调用方式一样,修改程序如下:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() int setup_daemon(int nochdir, int noclose);//模拟系统创建守护进程的函数声明 int main(int argc, char *argv[])
{
setup_daemon(, );//这时改用跟调用系统创建守护进程的自己实现的函数
printf("test ...\n");
for (;;) ;
return ;
} int setup_daemon(int nochdir, int noclose)
{
pid_t pid;
pid = fork();
if (pid == -)
ERR_EXIT("fork error"); if (pid > )
exit(EXIT_SUCCESS); setsid();
if (nochdir == 0)//实现很简单,做下参数判断既可
chdir("/");
if (noclose == 0)
{
int i;
for (i=; i<; ++i)
close(i);
open("/dev/null", O_RDWR);
dup();
dup();
}
return ; }

编译运行:

提示:在创建守护进程时,不重定向至空设备其实对于开发期间便于调试,如果等程序发布了之后,就得重定向了!】

好了,进程相关的东西就告一段落了,下节会继续探寻系统编程的其它东东,下节见!

linux系统编程之进程(五)的更多相关文章

  1. linux系统编程之进程(一)

    今天起,开始学习linux系统编程中的另一个新的知识点----进程,在学习进程之前,有很多关于进程的概念需要了解,但是,概念是很枯燥的,也是让人很容易迷糊的,所以,先抛开这些抽象的概念,以实际编码来熟 ...

  2. linux系统编程之进程(二):进程生命周期与PCB(进程控制块)

    本节目标: 进程状态变迁 进程控制块 进程创建 进程撤消 终止进程的五种方法 一,进程状态变迁 进程的三种基本状态 就绪(Ready)状态 当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便 ...

  3. Linux系统编程——Daemon进程

    目录 Daemon进程介绍 前提知识 Daemon进程的编程规则 Daemon进程介绍 Daemon运行在后台也称作"后台服务进程". 它是没有控制终端与之相连的进程.它独立与控制 ...

  4. linux系统编程之进程(六):父进程查询子进程的退出,wait,waitpid

    本节目标: 僵进程 SIGCHLD wait waitpid 一,僵尸进程 当一个子进程先于父进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行,或者父进程调用了wait才告终止. ...

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

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

  6. linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程

    本节目标: 复制进程映像 fork系统调用 孤儿进程.僵尸进程 写时复制 一,进程复制(或产生)      使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文.进程堆栈. ...

  7. linux系统编程--守护进程,会话,进程组,终端

    终端: 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal), 进程中,控制终端是保存在PCB中的信息,而f ...

  8. Linux系统编程之进程概念

    注:本文部分图片来源于网络,如有侵权,请告知删除 1. 什么是进程? 在了解进程概念之前,我们需要先知道程序的概念. 程序,是指编译好的二进制文件,这些文件在磁盘上,并不占用系统资源. 进程,指的是一 ...

  9. linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用

    本节目标: exec替换进程映像 exec关联函数组(execl.execlp.execle.execv.execvp) 一,exec替换进程映像 在进程的创建上Unix采用了一个独特的方法,它将进程 ...

随机推荐

  1. [资料]ObjectARX 2020参考指南翻译中文版

    chm使用Google Chrome浏览器翻译,有些翻译不是很理想,因为2万5千多个html文件, 修正难度太大,所以只处理了一部分. 非常感谢 gzxl 辛苦肉眼修正一些翻译问题. 欢迎进入QQ群: ...

  2. 使用clion+cmake+vcpkg的开发现代的c++跨平台程序

    使用clion+cmake+vcpkg的开发现代的c++跨平台程序 使用c++开发跨平台的程序 背景 在开发过程中,使用c++作为开发语言,通常被认为是痛苦的,啰嗦的,超长开发时间的.最近几年有各种各 ...

  3. ztree取消之前选中状态并设置新的选中

    var zTreeObject = $.fn.zTree.getZTreeObj("treeId"); var node = zTreeObject.getNodeByParam( ...

  4. python基础(三)-- 文件操作

    一. 文件操作: 对文件操作流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 现有文件如下 : Somehow, it seems the love I kn ...

  5. Jenkins运行python脚本出现 configparser.NoSectionError: No section: 'XXXXXX'

    原来的代码如下: def get_test_config(tag, key, config="config.ini"): cf = configparser.ConfigParse ...

  6. session知识点小结

    Session: 1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象HttpSession中. 2. 快速入门: 1. 获取HttpSession对象: Http ...

  7. centos7安装php7.3

    安装php7.3 CentOS/RHEL 7.x: yum install epel-release yum install http://rpms.remirepo.net/enterprise/r ...

  8. 【LEETCODE】43、1002. Find Common Characters

    package y2019.Algorithm.array; import java.util.*; /** * @ProjectName: cutter-point * @Package: y201 ...

  9. machine learning相关会议

    1. ICML(International Conference on Machine Learning)   链接:https://en.wikipedia.org/wiki/Internation ...

  10. LOJ3146 APIO2019路灯(cdq分治+树状数组)

    每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...