• UNIX环境高级编程——单实例的守护进程


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <signal.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <time.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <syslog.h>
    /* 创建守护进程函数 */
    int daemonize(){
    	int childpid, fd, fdtablesize;
    	int error, in, out;
    	/* 忽略终端I/O信号,STOP信号 */
    	signal(SIGTTOU, SIG_IGN); /* 后台进程写控制终端 */
    	signal(SIGTTIN, SIG_IGN); /* 后台进程读控制终端 */
    	signal(SIGTSTP, SIG_IGN); /* 终端挂起 */
    	signal(SIGHUP, SIG_IGN); /* 进程组长退出时向所有会议成员发出的 */
    	/* 父进程退出,子进程成为孤儿进程 */
    	if (fork()!=0)
    	    exit(1);
    	/* 设置新会话的领头进程,并与原来的登录会话和进程组脱离 */
    	if (setsid() == -1)
        	exit(1);
    	/* 防止会话组长重新申请控制终端,子进程退出,孙进程没有控制终端了 */
    	if (fork()!=0)
    	    exit(1);
    	/* 关闭打开的文件描述符,防止资源浪费和防止引起无法预料的错误 */
    	for (fd = 3, fdtablesize = getdtablesize();fd < fdtablesize;fd++){	
    		close(fd);
    	}
    	/* 重定向标准输入/标准输出和标准错误输出 */
    	error = open("./stderr", O_WRONLY|O_CREAT|O_APPEND, 0600);
    	dup2(error, 2);
    	close(error);
    	in = open("./stdin", O_RDONLY|O_CREAT,0600);
    	dup2(in, 0);
    	close(in);
    	out = open("./stdout", O_WRONLY|O_CREAT|O_APPEND,0600);
    	dup2(out, 1);
    	close(out);
    	/* 可以改变工作目录 */
    	/* chdir("/"); */
    	/* 重设文件创建掩模 */
    	umask(0);
    	/* 忽略SIGCHLD信号, 防止僵尸进程 */
    	signal(SIGCHLD, SIG_IGN);
    	return 0;
    }
    /* 单实例实现, 成功返回0, 失败程序退出, 打印错误或已运行进程号 */
    int already_running(const char *szLockFilePath){
    	int fd;
    	char szBuf[256] = { 0x00 };
    	
    	fd = open(szLockFilePath, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    	if (fd < 0){
    		memset(szBuf, 0x00, sizeof(szBuf));
    		sprintf(szBuf, "open LockFile failed!LockfilePath=[%s]/n", szLockFilePath);
    		perror(szBuf);
    		exit(1);
    	}
    	/* 尝试获取文件锁 */	
    	struct  flock fl;
    	memset(&fl, 0x00, sizeof(struct flock));
    	if (fcntl(fd, F_GETLK, &fl) < 0){
    		perror("fcntl get LockState failed!/n");
    		close(fd);
    		exit(1);
    	}
    	if (fl.l_type != F_UNLCK){
    		memset(szBuf, 0x00, sizeof(szBuf));
    		sprintf(szBuf, "已经有一个运行实例了。进程号为[%ld]/n", (long)fl.l_pid);
    		perror(szBuf);
    		close(fd);
    		exit(1);
    	}
    	fl.l_whence = SEEK_SET;/* 决定l_start的位置 */
    	fl.l_start =  0; /* 设置锁定区域开头位置 */
    	fl.l_len = 0; /* 设置锁定区域长度 */
    	fl.l_type = F_WRLCK;/* 设置锁定状态为写锁 */
    	fl.l_pid = getpid(); /* 设置锁进程号 */
    	/* 阻塞式加锁 */
    	if (fcntl(fd, F_SETLK, &fl) < 0){
    		perror("fcntl set Lockfile failed!/n");
    		close(fd);
    		exit(1);
    	}
    	/* 把进程号写入文件 */
    	ftruncate(fd, 0);
    	memset(szBuf, 0x00, sizeof(szBuf));
    	sprintf(szBuf, "%ld", (long)getpid());
    	write(fd, szBuf, strlen(szBuf)+1);
    	return 0;	
    }
    int main(void){
    	time_t now;
    	daemonize();
    	already_running("./MyDaemon.pid");
    	openlog("MyMsgDaemon", LOG_CONS | LOG_PID, 0);
    	syslog(LOG_DEBUG, "守护进程测试/n");
    	while (1){
    		time(&now);
    		syslog(LOG_DEBUG, "守护进程测试, 当前时间:[%s]/n", ctime(&now));
    		sleep(6);	
    	}
    	return 0;
    }	
    

  • 相关阅读:
    设置Centos7会话超时时间
    Shell浮点运算
    Maven 同一依赖多版本共存
    Java根据模板生成word
    Java条形码生成
    arcgis for js 4.x 悬浮显示popup
    tomcat 跨域配置
    Mysql8.0 版本 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',报错
    volatile
    synchronized
  • 原文地址:https://www.cnblogs.com/wangfengju/p/6172496.html
Copyright © 2020-2023  润新知