守护进程
进程组是一组进程的集合,进程组由进程组PID表示每个进程除了进程id之外,还必须有一个进程组id,即必须属于某个进程组每个进程组都有一个组长,其进程id就作为进程组id,它不受进程组长的退出影响。一般来说,一个终端一般是进程组长。会话期是由一个或多个进程组组成的集合
一个会话期开始于用户登录,结束于用户退出。在此期间用户运行的的所有进程都属于这个会话期。创建守护进程基本步骤
1.创建子进程 在终端输入命令执行用户程序时,该进程成为父进程,它此时受控制终端即创建该进程的控制终端控制,通过它创建子进程 让子进程脱离该终端的控制:子进程执行守护进程需要执行的代码,然后让父进程退出,此时子进程的父进程变为了系统的Init进程。 当父进程先于子进程退出,子进程成为孤儿进程。 在linux系统中,每当系统发现一个孤儿进程后,就会自动由1号进程(init进程) 收养它。 每个进程在创建时都有其自身的进程组、会话期及所属的控制终端,当创建子进程时,子进程复制父进程的这些属性,因此父子进程属于同一个进程组、会话期及控制终端2.让子进程脱离该终端的控制。当执行setsid()系统调用,使其脱离原终端控制。它创建一个新的会话并让调用它的进程成为该会话的组长,主要的3个作用 2.1 让进程摆脱原会话的控制 2.2 让进程摆脱原进程组的控制 2.3 让进程摆脱原控制终端的控制setsid()系统调用3.改变当前目录为根目录。 每个进程在执行时,都保存当前执行目录的信息。子进程也继承父进程的该信息 由于在进程运行过程中,当前目录所在的文件系统是不能卸载的, 这对以后的使用会造成诸多的麻烦(如用户要对不使用的目录进行卸载操作,由于该目录还在被守护进程使用,所以umount出错,导致该目录不能被卸载) 通常的做法是让系统根目录"/" 作为守护进程的的当前工作目录,会避免上述不必要的问题。当然,如果有特殊需要也可以把当前工作目录换成其它的路劲4.修改文件权限掩码 文件掩码是指屏蔽掉文件权限中的对应位。比如,一个文件的权限掩码是050,其对应的二进制码为000101000 表示屏蔽文件用户组用户读和执行的权限 由于新建子进程继承父进程的文件权限掩码,这就给该子进程操作文件带来诸多麻烦,因此,把文件权限掩码设置成0,即取消子进程对文件操作的限制, 从而大大增强该守护进程的灵活性,即调用umask(0)5.关闭文件描述符 同文件掩码一样,新建的子进程从父进程继承已经打开的文件描述符。这些被打开的文件描述符可能永远不会被守护进程读写,但它们同样耗费系统资源, 而且可能导致文件系统无法卸载。既然守护进程与控制终端失去了联系,因此与控制终端相关的文件描述符就不会被使用,如:文件描述符为 0,1,2(输入,输出和出错) 等文件描述符就不会被使用,失去存在的意义,要关闭它们,可使用close(fd)方法示例
#include#include #include #include #include #include #include #include #define MAXFILE 65535char *timestr();int main(){ pid_t pc; char wtr[100]; int i,fd,len; char *buf ="hello everybody!"; len=strlen(buf); pc=fork(); if(pc<0){ printf("fork err\n"); exit(1); } if(pc>0) exit(0); setsid(); chdir("/"); umask(0); for(i=0;i tm_hour, p->tm_min, p->tm_sec); return timestr;}
运行后
[root@centos1 c]# ./daemonhello everybody!-11:39:41[root@centos1 c]# ^C[root@centos1 c]# tail -f /tmp/daemon.loghello everybody!-11:39:43hello everybody!-11:39:45hello everybody!-11:39:47hello everybody!-11:39:49hello everybody!-11:39:51hello everybody!-11:39:53hello everybody!-11:39:55
目标 | 创建新会话 |
头文件 | #include <unistd.h>;#include <sys/types.h> |
函数原型 | pid_t pid=setsid(void) |
返回值 | 出错,返回-1 成功,返回该进程组的pid |