守护进程demo如下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LENGTH 128
char pid_name[] = "test";
static void start_daemon(const char *daemonName){
pid_t pid;
int fd,i,nullfd;
char buf[64] = {0};
char pid_file[LEN] = {0};
if (!daemonName)
exit(1);
fprintf(stdout,"Starting %s...\n",daemonName);
snprintf(pid_file,LENTGH,"/var/run/%s.pid",daemonName);
// 一、调用fork,终止父进程,留下子进程
// 1. 子进程继承了父进程的进程组ID
// 2. 子进程不是进程组的头进程,可以调用setsid
pid = fork();
if(pid < 0){
perror("Start daemon failed");
exit(1);
}else if(pid){
exit(0);
}
// 二、调用setsid
// 1.创建一个新的会话,<一>中的子进程1变为新会话的会话头进程
// 2.以及新进程组的进程组头进程,进程与控制终端脱离
setsid();
// 三、禁止进程重新打开控制终端
pid = fork();
if(pid < 0){
perror("Start daemon failed");
exit(1);
}else if(pid){
exit(0);
}
// 四、为错误处理函数设置标识
// 五、改变工作目录到根目录,若不更改目录,可能无法卸载所在的文件系统
if(chdir("/")<0){
perror("find workdir to proot failed");
exit(1);
}
// 六、关闭所有打开的描述符
// 1. 关闭继承过来的所有打开着的文件描述符
for (i = 3; i <1024 ; i++) {
close(i);
}
// 七、将stdin、stdout和stderr重定向到/dev/null
// 1. 打开/dev/null作文本守护进程的标准输入、输出、和错误输出
// 2. 确保这些描述符[0,1,2]打开,防止被其他套接字占用
nullfd = open("/dev/null",O_RDWR);
if(nullfd != -1){
dup2(nullfd, STDIN_FILENO);
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
if(nullfd > 2)
close(nullfd);
} else{
perror("Failed to open /dev/null");
exit(1);
}
fd = open(pid_file,O_WRONLY|O_CREAT,0644);
if(fd < 0){
perror("Unable to create pid file");
exit(1);
}
if(lockf(fd,F_TLOCK,0)<0){
perror("Unable to lock pid file");
exit(1);
}
if(ftruncate(fd,0)<0){
perror("Failed to ftruncate the PID file");
exit(1);
}
//sprintf(buf,"%d\n",(int)getpid());
//printf("pid = %s\n",buf);
if(write(fd,buf,strlen(buf))<strlen(buf)){
perror("Failed to write pid to the file");
exit(1);
}
}
int main() {
start_daemon(pid_name);
return 0;
}
6234

被折叠的 条评论
为什么被折叠?



