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

什么是守护进程:
 
 
 
守护进程的创建步骤:
在描述它之前,首先得先了解两个概念:进程组、会话期:
 
而它里面有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. 密码工具:KeePassXC

    KeePassXC 开源免费 只支持数据库存放在本地, 跨平台 自动填充 使用浏览器插件时,软件必须启动着 KeePassXC is a community fork of KeePassX, a n ...

  2. Kubernetes StatefulSet

    StatefulSet 简介 在Kubernetes中,Pod的管理对象RC.Deployment.DaemonSet和Job都是面向无状态的服务.但现实中有很多服务是有状态的,特别是一些复杂的中间件 ...

  3. svn服务安装教程

    https://www.cnblogs.com/yankyblogs/p/7282752.html

  4. 从GitLab上创建分支本地拉取项目和提交项目详解

    很多公司前端项目都是部署在GitLab上的,今天我要分享的就是如何从GitLab上创建新的分支并在本地拉取和提交项目 一.在GitLab上面创建自己新的分支 首先你得注册一个账号,登陆之后进入项目Pr ...

  5. [转帖]微软宣布加入 OpenJDK 项目

    微软宣布加入 OpenJDK 项目 https://news.cnblogs.com/n/646003/ 近日,微软的 Bruno Borges 在 OpenJDK 邮件列表中发布了一条消息,内容包含 ...

  6. Charles手机代理设置

      Charles工具 手机 方法/步骤     1.打开Charles   点击Proxy,选择proxy settings,输入端口8888   打开电脑,在cmd中输入ipconfig,查看本地 ...

  7. Django——用户认证

    Django--用户认证 用户与Authentication(身份验证) Django 用户认证系统处理用户帐号,组,权限以及基于cookie的用户会话. 这个系统一般被称为 auth/auth (认 ...

  8. 08-Maps

    Maps map 是在 Go 中将值(value)与键(key)关联的内置类型.通过相应的键可以获取到值.Maps类似于python中的字典 Maps定义 maps的key值必须是可hash(就是不可 ...

  9. Linux忘记root密码操作方法

    此方法为:进入单用户模式,直接修改新密码覆盖掉以前的root密码. 操作步骤: 1.进入单用户模式 2.修改root密码 1.进入单用户方法: 1)启动Linux时,通过按上下键(其他键也可以)让Li ...

  10. 小程序发起get请求====post请求