linux c 笔记 进程控制(二)---守护进程

守护进程(Daemon),一说精灵进程,是指在后台运行的,没有控制终端与之相连的程序.它独立于控制终端周期性地执行某种任务或等待处理某些发生的事件。它是一个生存期较长的进程,守护进程常常在系统引导装入时启动,在系统关闭时终止。Linux系统有很多守护进程,大多数服务都是通过守护进程实现的,同时,守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)。
由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能够突破这种限制,它从被执行开始运转,直到整个系统关闭时才退出。如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。守护进程在后台运行,类似于windows中的系统服务
    守护进程的启动方式有多种,它可以在linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由终端(通常是shell)执行.
    编写创建守护进程的程序,要尽量避免产生不必要的交互,编写
    创建守护进程的程序有以下要点:
    1)创建子进程,父进程退出
    这是编写守护进程的第一步。由于守护进程是脱离控制终端的,因此,完成第一步后就会在Shell终端里造成一程序已经运行完毕的假象。之后的所有工作都在子进程中完成,而用户在Shell终端里则可以执行其他命令,从而在形式上做到了与控制终端的脱离。
    在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程时,就会自动由1号进程(init)收养它,这样,原先的子进程就会变成init进程的子进程。
    2)在子进程中创建新会话
这个步骤是创建守护进程中最重要的一步,虽然它的实现非常简单,但它的意义却非常重大。在这里使用的是系统函数setsid,创建一个新对话,控制终端,登陆会话和进程组通常是从父进程继承下来的,守护进程要摆脱他们,不受他们影响,其方法是调用setsid使进程成为一个会话组长

进程组:是一个或多个进程的集合。进程组有进程组ID来唯一标识。除了进程号(PID)之外,进程组ID也是一个进程的必备属性。每个进程组都有一个组长进程,其组长进程的进程号等于进程组ID。且该进程组ID不会因组长进程的退出而受到影响。

一个进程创建了子进程,父子进程可以构成一个进程组,父进程的PID就是这个组的组id
    会话有多个进程组构成,每次登录一次系统,就是一个会话
    进程组是一个或多个进程的集合,每个进程组有一个组长( 其进程ID=进程组ID ),组长进程终止时,进程组依然存在。
    会话周期:会话期是一个或多个进程组的集合。通常,一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。

会话和进程组有一些特性:

1). 一个会话可以有一个控制终端。
2). 建立与控制终端连接的会话首进程被称为控制进程。
3). 一个会话中的几个进程组可被分成一个前台进程组和几个后台进程组。
4). 如果一个会话有一个控制终端,则它有一个前台进程组。
5). 无论何时键入终端的中断键(DELETE或Ctrl+C),就会将中断信号发送给前台进程组的所有进程。
6). 无论何时键入终端的退出键(Ctrl+\),就会将退出信号发送给前台进程组的所有进程。
7). 如果终端检测到调制解调器(或网络)已经断开连接,则将挂断信号发送给控制进程(会话首进程)。

setsid():当进程是会话的领头进程时setsid()调用失败并返回(-1)。setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。由于会话对控制终端的独占性,进程同时与控制终端脱离。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/types.h>
 4 #include <sys/param.h>
 5 #include <unistd.h>
 6 #include <signal.h>
 7 #include <sys/stat.h>
 8 #include <time.h>
 9 #include <syslog.h>
10
11
12 int init_daemon()
13 {
14     int pid ;
15     int i;
16
17     /*忽略终端I/O信号,STOP信号*/
18     signal(SIGTTOU ,SIG_IGN);
19     signal(SIGTTIN ,SIG_IGN);
20     signal(SIGTSTP ,SIG_IGN);
21     signal(SIGHUP ,SIG_IGN);
22
23     pid = fork();
24     if(pid >0 ){
25         exit (0);//结束父进程,是子进程成为后台程序
26     }
27     else if(pid < 0){
28         return -1;
29     }
30     //建立一个新进程组,在这个新进程里,子程序成为这个进程组的首进程,以使该进程脱离所有终端
31     setsid();
32
33     //再次新建一个子进程,退出父进程,保证该进程不是进程组长,同时让该进程无法在打开一个新的终端
34     pid =fork();
35     if( pid > 0) {
36         exit(0);
37     }
38     else if ( pid <0 ) {
39         return -1;
40     }
41     //关闭所有从父进程继承的不再需要的文件描述符
42     for (i =0 ; i<NOFILE ;close(i++ ));
43     //改变工作目录,使进程不与任何文件系统联系
44     chdir("/");
45     //将文件屏蔽字设置为0
46     umask(0);
47
48     //忽略SIGHLD信号
49     signal(SIGCHLD,SIG_IGN);
50
51     return 0;
52 }
53
54
55 int main()
56 {
57     time_t now;
58     init_daemon();
59     syslog(LOG_USER | LOG_INFO ,"测试守护进程!\n");
60     while (1){
61         sleep(8);
62         time(&now );
63         syslog(LOG_USER | LOG_INFO ,"系统时间:\t%s\t\t\n",ctime(&now));
64     }
65 } 

setsid()之后又加了一步fork()创建子进程exit()使父进程退出,原因是,此时的子进程已经成为会话组的组长,有权利再调出一个终端,如果出现此情况,则未达到完全脱离终端的目的,此时再调用fork并退出父进程,使得此时的子进程成为完全的后台进程,独立于任何的终端。

时间: 2024-10-18 18:07:00

linux c 笔记 进程控制(二)---守护进程的相关文章

Linux环境编程之进程(七):守护进程

守护进程也是一种进程,它由如下特性: 1.生存期较长,在系统自举时启动,仅在系统关闭时终止. 2.没有控制终端,在后台运行. 系统中有很多守护进程,它们执行日常事务活动.如日志进程syslogd.web服务器httpd.邮件服务器sendmail和数据块服务器mysqld等.大多数守护进程都是以超级用户(用户ID为0)特权运行.没有一个守护进程具有控制终端,其终端设置为问号(?),终端前台进程组ID设置为-1.内核守护进程以无控制终端方式启动.用户层守护进程缺少控制终端可能是守护进程调用了set

Linux系统开发7 进程关系,守护进程

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统开发7  进程关系守护进程 终端 网络终端 Linux PCB结构体信息 进程组 修改子进程.父进程的组ID 会话组 设置一个会话脱离控制终端 生成一个新的会话 守护进程 守护进程模板 获取当前系统时间  终端 在UNIX系统中用户通过终端登录系统后得到一个Shell进程这个终端成为Shell进 程的控制终端Controlling Terminal在讲进程时讲过控制终端是保存在PCB

《APUE》读书笔记第十三章-守护进程

守护进程 守护进程是生存期较长的一种进程,它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNIX系统由很多守护进程,它们执行日常事务活动. 本章主要介绍守护进程的结构,以及如何编写守护进程程序和守护进程如何报告错误情况. 一.守护进程的编程规则 (1)首先要做的是调用umask将文件模式创建屏蔽字设置为0.这是由于继承得来的文件模式创建屏蔽字可能会拒绝设置某些权限. (2)调用fork,然后使父进程退出(exit). (3)调用setsid以创建

《Unix环境高级编程》读书笔记 第13章-守护进程

1. 引言 守护进程是生存期长的一种进程.它们常常在系统引导装入时启动,仅在系统关闭时才终止.它们没有控制终端,在后台运行. 本章说明守护进程结构.如何编写守护进程程序.守护进程如何报告出错情况. 2. 守护进程的特征 基于BSD的系统下执行:ps -axj -a 显示由其他用户所拥有的进程的状态:-x 显示没有控制终端的进程状态:-j 显示与作业有关的信息 基于System V的系统下执行:ps -efj Linux下执行以上两个命令输出一致 常见的守护进程: kswapd,内存换页守护进程.

进程控制、孤儿进程和僵尸进程

一.进程控制 1.进程标识 1.操作系统里每打开一个进程都会创建一个进程ID,这是唯一标识进程的编号,即PID. 2.PID 在任何时刻都是唯一的,但是可以重用.当进程终止并被回收以后,其 PID 就会被系统回收 3.进程的 PID 由系统内核根据延迟重用算法生成,以确保新进程的 PID 不同于最近终止进程的 PID. 4.进程PID的最大值是有限的(因系统的不同而不同),需要及时回收 2.特殊进程 0 号进程:通常是调度进程,常常被称为交换进程(swapper).该进程是内核的一部分,所有进程

(七) 一起学 Unix 环境高级编程(APUE) 之 进程关系 和 守护进程

. . . . . 目录 (一) 一起学 Unix 环境高级编程(APUE) 之 标准IO (二) 一起学 Unix 环境高级编程(APUE) 之 文件 IO (三) 一起学 Unix 环境高级编程(APUE) 之 文件和目录 (四) 一起学 Unix 环境高级编程(APUE) 之 系统数据文件和信息 (五) 一起学 Unix 环境高级编程(APUE) 之 进程环境 (六) 一起学 Unix 环境高级编程(APUE) 之 进程控制 (七) 一起学 Unix 环境高级编程(APUE) 之 进程关系

进程控制之孤儿进程

#include<stdio.h> #include<sys/types.h> #include<sys/wait.h> #include<unistd.h> #include<signal.h> int main( void ) { daemon_init(); fprintf(stderr, "main进程[%d]\n", getpid() ); while( 1 ) { } exit(0); } int daemon_i

进程控制(二)与linux下的自有服务

一.进程动态信息查看top 第一部分 统计信息 [[email protected] ~]# top top - 19:22:52 up 1:32, 2 users, load average: 0.00, 0.00, 0.00 Tasks: 106 total, 1 running, 105 sleeping, 0 stopped, 0 zombie Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.6%id, 0.0%wa, 0.0%hi, 0.2%si, 0.0%st

Linux 进程(二):进程关系及其守护进程

进程关系 进程组 进程组是一个或多个进程的集合.通常,它们是在同一作业中结合起来的,同一进程组中的各进程接收来自同一终端的各种信号,每个进程组有一个唯一的进程组ID.每个进程组有一个组长进程,该组长进程的ID等于进程组ID.从进程组创建开始到最后一个进程离开为止的时间称为进程组的生命周期. #include <unistd.h> pid_t getpgrp(void); 返回值:调用进程的进程组ID int setpgid(pid_t pid, pid_t pgid); 返回值:成功,返回0:

docker 学习笔记20:docker守护进程的配置与启动

安装好docker后,需要启动docker守护进程.有多种启动方式. 一.服务的方式 因为docker守护进程被安装成服务.所以,可以通过服务的方式启停docker守护进程,包括查看状态. sudo start docker  //启动 sudo stop docker  //停止 sudo status docker  //查看状态 二.利用docker daemon命令 sudo docker daemon 利用sudo ps -A 可以获取守护进程的进程号 三.让远程api可以访问dock