一.概述:守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是随系统启动而存在,随系统关闭而消失的进程(也就是开机之后就会存在,关机才消失)。守护进程是一种很有用的进程,Linux的大多数服务器就是用守护进程实现的。
在终端运行命令:ps axj | head
参数a表示不仅列出当前用户进程,也列出所有其它用户进程。
参数x表示不仅列出有控制终端的进程,也列出所有无控制终端的进程。
Linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着,直到电脑关机。
凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。在COMMAND一列用[]括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行, 通常采用以k开头的名字,表示Kernel。init进程是内核启动的第一个用户级进程,init有许多很重要的任务,比如象启动getty(用于用户登录)、实现运行级别、以及处理孤儿进程。udevd负责维护/dev目录下的 设备文件,acpid负责电源管理,syslogd负责维护/var/log下的日志文件,可以看出,守护进程通 常采用以d结尾的名字,表示Daemon。
二.创建一个守护进程:
创建守护进程最关键的一步是调用setsid函数创建一个新的会话(Session),并成为Session Leader。
int setsid(void)
该函数调用成功时返回新创建的Session的id(也就是当前进程的id),出错返回-1。
成功调用用该函数的结果是:
1. 创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
2.创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
3. 如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。
三.创建一个守护进程的过程:
1.调用umask将文件模式创建屏蔽字设置为0。
2. 调用fork,父进程退出(exit)。原因:(1).如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得shell认为该命令已经执行完毕。(2).保证子进程不是一个进程组的组长进程。
3. 调用setsid创建一个新会话。setsid会导致:(1)调用进程成为新会话的首进程。 (2).调用用
进程成为一个进程组的组长进程 。(3).调用进程没有控制终端。(也可以再次fork一次,保证daemon进程,之后不会打开tty设备)
4. 将当前工作目录更改为根目录。
5. 关闭不在需要的文件描述符。
6. 其他:忽略SIGCHLD信号。
四.创建一个守护进程的相关代码:(守护进程的内容可以自己定义)
1 /**************************************** 2 > File Name:create_daemon.c 3 > Author:xiaoxiaohui 4 > mail:1924224891@qq.com 5 > Created Time:2016年05月10日 星期二 20时31分11秒 6 ****************************************/ 7 8 #include<stdio.h> 9 #include<stdlib.h> 10 #include<string.h> 11 #include<signal.h> 12 #include<unostd.h> 13 #include<fcntl.h> 14 #include<sys/stat.h> 15 #include<sys/types.h> 16 17 int main() 18 { 19 pid_t pid; 20 FILE* fd; 21 char* buf = "i‘m a daemon\n"; 22 23 umask(0); //第一步,设置文件掩码为0 24 25 pid = fork(); //第二步,创建子进程 26 if(pid < 0) 27 { 28 printf("fork errored \n"); 29 exit(0); 30 } 31 else if(pid > 0) 32 { 33 exit(0); 34 } 35 else //子进程 36 { 37 setsid(); //第三步,创建新会话 38 39 chdir("/"); //第四步,改变当前工作目录 40 41 close(1); //第五步,关闭不必要的文件描述符 42 close(2); 43 close(3); 44 45 signal(SIGCHLD,SIG_IGN);//忽略SIGCHLD信号 46 47 while(1) 48 { 49 } 50 51 return 0; 52 }
本文出自 “水仙花” 博客,请务必保留此出处http://10704527.blog.51cto.com/10694527/1772130
原文地址:http://10704527.blog.51cto.com/10694527/1772130