学习笔记:fork实现守护进程

目标: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值