C语言写监控守护进程
文章转自王牌软件
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
只回答业务咨询
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <syslog.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> #include <sys/wait.h> #define TCP_PORT 8888 int daemon(int,int); int fork2(void); void closeall(int); 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; } /* 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; } |
学习日记,兼职软件设计,软件修改,毕业设计。
本文出自 学习日记,转载时请注明出处及相应链接。
本文永久链接: https://www.softwareace.cn/?p=483