在linux中用c语言编写一个守护进程,实现如下功能: a) 当前程序实例只能存在一个,重复运行会提醒用户程序已经运行; b) 每秒向os用户空间timer文件写入当前已经运行的秒数; c) 能够向当前程序实例传入指令,使其能够终止。
时间: 2024-01-22 08:18:01 浏览: 84
好的,以下是一个简单的守护进程示例程序,可供参考。
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PID_FILE "/var/run/mydaemon.pid"
#define TIMER_FILE "/tmp/mydaemon.timer"
static int pid_fd = -1;
static void signal_handler(int sig) {
switch (sig) {
case SIGHUP:
break;
case SIGTERM:
if (pid_fd >= 0) {
close(pid_fd);
unlink(PID_FILE);
}
exit(EXIT_SUCCESS);
break;
default:
break;
}
}
static void daemonize() {
pid_t pid, sid;
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
} else if (pid > 0) {
exit(EXIT_SUCCESS);
}
umask(0);
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
if (chdir("/") < 0) {
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
static int write_timer() {
int fd, ret;
char buf[64];
time_t now = time(NULL);
fd = open(TIMER_FILE, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (fd < 0) {
fprintf(stderr, "Failed to open timer file: %s\n", strerror(errno));
return -1;
}
sprintf(buf, "%ld\n", now);
ret = write(fd, buf, strlen(buf));
if (ret < 0) {
fprintf(stderr, "Failed to write timer file: %s\n", strerror(errno));
close(fd);
unlink(TIMER_FILE);
return -1;
}
close(fd);
return 0;
}
int main(int argc, char *argv[]) {
int ret;
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
ret = sigaction(SIGHUP, &sa, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to set signal handler for SIGHUP: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
ret = sigaction(SIGTERM, &sa, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to set signal handler for SIGTERM: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
daemonize();
pid_fd = open(PID_FILE, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (pid_fd < 0) {
fprintf(stderr, "Failed to open PID file: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
char pid_str[16];
sprintf(pid_str, "%d\n", getpid());
ret = write(pid_fd, pid_str, strlen(pid_str));
if (ret < 0) {
fprintf(stderr, "Failed to write PID file: %s\n", strerror(errno));
close(pid_fd);
unlink(PID_FILE);
exit(EXIT_FAILURE);
}
while (1) {
ret = write_timer();
if (ret < 0) {
break;
}
sleep(1);
}
exit(EXIT_SUCCESS);
}
```
代码中包括以下功能:
1. 将程序变为守护进程,通过 `daemonize()` 函数实现。
2. 在 `/var/run/mydaemon.pid` 文件中写入守护进程的 PID,如果该文件已存在,则提醒用户程序已经运行。
3. 每秒向 `/tmp/mydaemon.timer` 文件中写入当前已经运行的秒数。
4. 可以通过捕获 `SIGHUP` 和 `SIGTERM` 信号来终止程序,SIGTERM 信号会在程序被kill时自动发送。
请注意,如果您要运行此代码,请先创建 `/var/run` 和 `/tmp` 目录,以及相应的文件,并使用 root 用户运行程序。如果您不想使用 root 用户运行程序,可以将文件路径改为普通用户可写的路径。
阅读全文