本文共 1817 字,大约阅读时间需要 6 分钟。
/* 父进程退出 */ if (fork() != 0) { exit(1); } if (setsid() < 0) { exit(1); } if (fork() != 0) { exit(1); } sprintf(app_dir_path, "%s/%s", WORK_DIR_PATH, APP_DIR_PATH); if (chdir(app_dir_path) == -1) { printf("chdir %s failed,taskd exit!\n",app_dir_path); exit(1);
}
为什么fork两次?
1进程组首进程不能调用setsid,会得到EPERM错误,这就是第一个fork的原因,执行第一个fork并让父进程退出,子进程继续,这时候由于子进程会继承其父进程的进程组GID并有自己的进程PID,而这个PID和GID肯定是不一样的。所子进程绝不可能成为进程组首进程,满足了调用setsid的条件。
2调用setsid后所有到之前控制终端的连接都会断开。
最后,再执行一次fork,让子进程退出,孙进程继续。这样让孙进程pid不等于它所在的会话sid,这样它就不会自己变成会话首进程,也就使它不能打开控制终端。这样守护进程就得到了一个干净的环境,它不会被终端产生的信号干扰。 经过前面2个步骤,基本想要做的都做了。第2次fork不是必须的。也看到很多开源服务没有fork第二次。fork第二次主要目的是。防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次,子进程ID != sid(sid是进程父进程的sid)。所以也无法打开新的控制终端。
(chdir(app_dir_path) 产生的此子进程或孙进程可能不在/home/app里面工作,需要重新更改工作目录 理解:此程序是守护进程的部分代码,
1、在实际应用中,代码需要从当前目录进到其它目录,完成操作,然后再回到当前目录。这个时候需要getcwd获取当前目录路径,保存起来,在使用chdir跳转到其它目录,然后再使用chdir和保存的路径回到最初的目录。
2、man chdir
3、int chdir(const char *path);
-参数*path;文件路径
-返回值;成功返回0,错误返回-1.
4、例:
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
- #include <unistd.h>
-
- #define LENTH 255
-
- int main(int argc,char *argv[])
- {
- int ret;
- char pwd[LENTH];
-
-
- if(argc <3){
- printf("\nPlease input file path\n");
- return 1;
- }
-
-
- if(!getcwd(pwd,LENTH)){
- perror("getcwd");
- return 1;
- }
- printf("\ngetcwd pwd is %s\n",pwd);
-
-
- ret = chdir(argv[1]);
- if(ret){
- printf("Please make sure file path\n");
- return 1;
- }
- printf("chdir %s is success!\n",argv[1]);
-
-
-
- ret = rmdir(argv[2]);
- if(ret<0){
- printf("rmdir %s failed!\n",argv[2]);
- return 1;
- }
- printf("rmdir %s is success!\n",argv[2]);
-
-
- ret = chdir(pwd);
- if(ret){
- printf("Please make sure file path\n");
- return 1;
- }
- printf("chdir %s is success!\n",pwd);
-
- return 0;
- }