目标:fork的父进程作为守护进程监测子进程,如果子进程挂了,则可以实现子进程的重启。
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include <sys/prctl.h>
#include <sys/shm.h> //共享内存一定要包含这个头文件, 否则运行会出现段错误
#include <sys/ipc.h>
/**
1 SIGHUP 挂起
2 SIGINT 中断
3 SIGQUIT 退出
4 SIGILL 非法指令
5 SIGTRAP 断点或陷阱指令
6 SIGABRT abort发出的信号
7 SIGBUS 非法内存访问
8 SIGFPE 浮点异常
9 SIGKILL kill信号 不能被忽略、处理和阻塞
10 SIGUSR1 用户信号1
11 SIGSEGV 无效内存访问
12 SIGUSR2 用户信号2
13 SIGPIPE 管道破损,没有读端的管道写数据
14 SIGALRM alarm发出的信号
15 SIGTERM 终止信号
16 SIGSTKFLT 栈溢出
17 SIGCHLD 子进程退出 默认忽略
18 SIGCONT 进程继续
19 SIGSTOP 进程停止 不能被忽略、处理和阻塞
20 SIGTSTP 进程停止
21 SIGTTIN 进程停止,后台进程从终端读数据时
22 SIGTTOU 进程停止,后台进程想终端写数据时
23 SIGURG I/O有紧急数据到达当前进程 默认忽略
24 SIGXCPU 进程的CPU时间片到期
25 SIGXFSZ 文件大小的超出上限
26 SIGVTALRM 虚拟时钟超时
27 SIGPROF profile时钟超时
28 SIGWINCH 窗口大小改变 默认忽略
29 SIGIO I/O相关
30 SIGPWR 关机 默认忽略
31 SIGSYS 系统调用异常
**/
void* child_thread(void* data)
{
int cnt = 0;
while(1){
printf("child_thread cnt = %d...\n", cnt++);
usleep(1000000);
}
return NULL;
}
int main(void) {
pid_t pid;
int status = 0;
int shmid;
int* shmaddr;
int cnt = 0;
shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
if(shmid < 0) {
printf("get shmid fail\n");
return -1;
}
shmaddr = (int*)shmat(shmid, NULL, 0);
if(shmaddr == (void*)-1) {
printf("shmat fail\n");
exit(2);
}
*shmaddr = cnt;
shmdt(shmaddr);
while(1) {
pid = fork();
if (pid < 0) {
printf("fork failed.\n");
usleep(1000000);
continue;
}
else if (pid == 0){
shmaddr = (int*)shmat(shmid, NULL, 0);
if(shmaddr == (void*)-1) {
printf("shmat fail\n");
exit(2);
}
printf("this is the child process: %d.\n", *shmaddr);
shmdt(shmaddr);
//prctl(PR_SET_NAME, "child", NULL, NULL, NULL);
pthread_t id;
pthread_create(&id, NULL, &child_thread, NULL);
#if 0
int cnt = 0;
while(cnt < 5){
printf("I am child %d\n", cnt++);
usleep(1000000);
}
printf("child is over\n");
//return 0; //exit normal
//exit(0);
//exit(-1);
exit(3);
#else
printf("test segment fault\n");
int *p = NULL;
*p = 10;
while(1);
#endif
}else{
printf("this is the parent process.child PID:%d\n", pid);
prctl(PR_SET_NAME, "child_daemon", NULL, NULL, NULL);
/*
* status 只用到低16位
* 0 - 6 : 表示使进程退出的信号
* 8 - 15: 表示使进程退出的返回码
*/
printf("start to monitor child process.....\n");
waitpid(-1, &status, 0);
if(WIFEXITED(status)) {
printf("child process is exit(%d)\n", WEXITSTATUS(status));
exit(0);
}
else if(WIFSIGNALED(status)) {
switch (WTERMSIG(status)) {
case SIGKILL:
printf("child process is termimate by SIGKILL.\n");
exit(0);
case SIGINT:
case SIGTERM:
printf("child process is termimate by SIGINT or SIGTERM.\n");
exit(1);
default:
printf("child process is terminate by SIG: %d\n", WTERMSIG(status));
break;
}
}
else {
printf("child process is terminate unknow reason fork again\n");
}
shmaddr = (int*)shmat(shmid, NULL, 0);
if(shmaddr == (void*)-1) {
printf("shmat fail\n");
exit(2);
}
*shmaddr = ++cnt;
shmdt(shmaddr);
}
usleep(1000000);
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}