⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deamon.cpp

📁 在Linux下实现守护进程的标准代码
💻 CPP
字号:
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
   /* closeall() -- 关闭所有>=给定值的文件描述符 */
   void closeall(int fd)
{
   int fdlimit = sysconf(_SC_OPEN_MAX);
   while (fd < fdlimit)
     close(fd++);
}
   /* daemon() - 将进程从用户端脱离并消失进入后台,若失败返回-1,
* 但是在那种情况下你只能退出,因为我们可能已经生成了子进程。
* 这是基于BSD的版本,所以调用方需负责类似umask等等其它的工作。
*/
   /* 相信在所有Posix系统上都能工作 */
   int daemon(int nochdir, int noclose)
{
   switch (fork())
   {
       case 0:  break;
       case -1: return -1;
       default: _exit(0);          /* 原进程退出 */
   }
       if (setsid() < 0)               /* 不应该失败 */
     return -1;
/* 如果你希望将来获得一个控制tty,则排除(dyke)以下的switch语句 */
/* -- 正常情况不建议用于守护程序 */
   switch (fork())
   {
       case 0:  break;
       case -1: return -1;
       default: _exit(0);
   }
       if (!nochdir)
     chdir("/");
       if (!noclose)
   {
       closeall(0);
       open("/dev/null",O_RDWR);
       dup(0); dup(0);
   }
       return 0;
}
/* fork2() -- 类似fork函数,但子进程立刻变成孤儿进程
*            (当它退出时不产生僵死进程)
* 返回1给父进程,不是任何有意义的进程号.
* 父进程不能使用wait函数等待子进程结束 (它们是无关的).
*/
/* 这个版本假设你没有捕获和忽略SIGCHLD信号. */
/* 如果你有设定,则不管怎样应使用fork函数 */
int fork2()
{
   pid_t pid;
   int rc;
   int status;
       if (!(pid = fork()))
   {
       switch (fork())
       {
         case 0:  return 0;
         case -1: _exit(errno);    /* 假设错误码都小于256 */
         default: _exit(0);
       }
   }
       if (pid < 0 || waitpid(pid,&status,0) < 0)
     return -1;
       if (WIFEXITED(status))
     if (WEXITSTATUS(status) == 0)
       return 1;
     else
       errno = WEXITSTATUS(status);
   else
     errno = EINTR;  /* 唉,类似这个 :-) */
       return -1;
}
//一个使用以上函数的范例程序:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
   int daemon(int,int);
int fork2(void);
void closeall(int);
   #define TCP_PORT 8888
   void errexit(const char *str)
{
   syslog(LOG_INFO, "%s failed: %d (%m)", str, errno);
   exit(1);
}
   void errreport(const char *str)
{
   syslog(LOG_INFO, "%s failed: %d (%m)", str, errno);
}
  /* 实际的子进程在此. */
   void run_child(int sock)
{
   FILE *in = fdopen(sock,"r");
   FILE *out = fdopen(sock,"w");
   int ch;
       setvbuf(in, NULL, _IOFBF, 1024);
   setvbuf(out, NULL, _IOLBF, 1024);
       while ((ch = fgetc(in)) != EOF)
     fputc(toupper(ch), out);
   fclose(out);
}
/* 这是守护程序的主要工作 -- 侦听连接并生成子进程 */
void process()
{
   struct sockaddr_in addr;
   int addrlen = sizeof(addr);
   int sock = socket(AF_INET, SOCK_STREAM, 0);
   int flag = 1;
   int rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
                       &flag, sizeof(flag));
 if (rc < 0)
     errexit("setsockopt");
   addr.sin_family = AF_INET;
   addr.sin_port = htons(TCP_PORT);
   addr.sin_addr.s_addr = INADDR_ANY;
   rc = bind(sock, (struct sockaddr *) &addr, addrlen);
   if (rc < 0)
     errexit("bind");
   rc = listen(sock, 5);
   if (rc < 0)
     errexit("listen");
   for (;;)
   {
       rc = accept(sock, (struct sockaddr *) &addr, &addrlen);
       if (rc >= 0)
         switch (fork2())
         {
           case 0:  close(sock); run_child(rc); _exit(0);
           case -1: errreport("fork2"); close(rc); break;
           default: close(rc);
         }
   }
}
int main()
{
   if (daemon(0,0) < 0)
   {
       perror("daemon");
       exit(2);
   }
   openlog("test", LOG_PID, LOG_DAEMON);
   process();
   return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -