守护进程
守护进程:也就是通常所说的Daemon进程,是linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务或者等待处理某些发生的事件。
守护进程常常在系统启动时开始运行,在系统关闭时终止。
linux系统有很多守护进程,大多数服务都是用守护进程实现的。
linux守护进程的编写步骤:
1、创建子进程,父进程退出;
第一步完成后,子进程就在形式上做到了与控制端的脱离
由于父进程已经先于子进程退出,子进程变成孤儿进程。
pid = fork();
if(pid > 0)
{
exit(0);
}
2、在子进程中创建新会话;
setsid 函数作用用于创建一个新的会话,并使得当前进程成为新会话组的组长
setsid 函数能够使进程完全独立出来,从而脱离所有其他进程的控制。
3、改变当前目录为根目录;
通常的做法是让“/”或者“/tmp”作为守护进程的当前工作目录。
在进程运行过程中,当前目录所在的文件系统是不能卸载的。
chdir函数可以改变进程当前工作目录。
4、重设文件权限掩码
文件权限掩码是指文件权限中被屏蔽掉的对应位。把文件权限掩码设置为0,可以增加对该守护进程的灵活性。
设置文件权限掩码的函数是umask
通常的使用方法为umask(0)
5、关闭文件描述符
新建的子进程会从父进程那里继承所有已经打开的文件。
在创建完新的会话后,守护进程已经脱离任何控制终端,应当关闭用不到的文件
close(...);
示例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <errno.h> 5 #include <time.h> 6 #include <string.h> 7 8 void deamon_mode() 9 { 10 pid_t pid; 11 12 //创建子进程,父进程退出 13 if((pid = fork()) < 0) 14 { 15 perror("Fail fork"); 16 exit(EXIT_FAILURE); 17 } 18 19 if(pid > 0) 20 { 21 exit(EXIT_SUCCESS); 22 } 23 24 //创建新会话期 25 if(setsid() < 0) 26 { 27 perror("Fail to setsid"); 28 exit(EXIT_FAILURE); 29 } 30 31 //改变工作目录为"/" 32 chdir("/"); 33 34 //重设文件掩码 35 umask(0); 36 37 //关闭不需要的文件描述符 38 close(0); 39 close(1); 40 close(2); 41 42 return ; 43 } 44 45 int get_line(FILE *fp) 46 { 47 int line = 0; 48 char buf[1024]; 49 50 //buf:....\n\0 51 while(fgets(buf,sizeof(buf),fp) != NULL) 52 { 53 if(buf[strlen(buf) - 1] == '\n') 54 line ++; 55 } 56 57 return line; 58 } 59 60 void do_log(char *name) 61 { 62 FILE *fp; 63 time_t tim; 64 struct tm *ptm; 65 int line = 0; 66 67 if((fp = fopen(name,"a+")) == NULL) 68 { 69 fprintf(stderr,"Fail to fopen %s : %s.\n",name,strerror(errno)); 70 return; 71 } 72 73 line = get_line(fp); 74 75 while(1) 76 { 77 tim = time(NULL); 78 ptm = localtime(&tim); 79 80 fprintf(fp,"%d,%d-%d-%d %d:%d:%d.\n",++line,ptm->tm_year + 1900,ptm->tm_mon + 1,\ 81 ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec); 82 83 fflush(fp); 84 sleep(1); 85 } 86 87 return ; 88 } 89 90 //练习:守护进程写日志 91 92 //./a.out -d 进程守护进程模式 93 //./a.out 非守护进程模式 94 //./a.out -d file 95 //./a.out file 96 int main(int argc, char * const argv[]) 97 { 98 int ch; 99 int flag = 0; 100 101 while((ch = getopt(argc,argv,"d")) != -1) 102 { 103 switch(ch) 104 { 105 case 'd': 106 flag = 1; 107 break; 108 } 109 } 110 111 if(flag) 112 { 113 deamon_mode(); 114 } 115 116 do_log(argv[optind]); 117 118 exit(EXIT_SUCCESS); 119 }