学习网址:
学习笔记:fork实现守护进程
https://blog.youkuaiyun.com/u010312436/article/details/81778865
1.进程产生的信号:
/**
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 系统调用异常
**/
//引用网址: https://blog.youkuaiyun.com/u010312436/article/details/81778865
2.fork的返回值
fork会返回两次,返回值:
(1) >0 在父进程中,fork返回新创建子进程的进程ID; 注意这里是返回"子进程的pid"
(2) ==0 在子进程中,fork返回0;
(3) <0 如果出现错误,fork返回一个负值。
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[]){
pid_t pid=fork();
if ( pid < 0 ) {
fprintf(stderr,"错误!");
} else if( pid == 0 ) {
printf("子进程空间");
exit(0);
} else {
printf("父进程空间,子进程pid为%d",pid);
}
// 可以使用wait或waitpid函数等待子进程的结束并获取结束状态
exit(0);
}
3 waitpid函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);
调用waitpid()函数时两种情况
<1>当指定等待的子进程已经停止运行或结束了,则waitpid()会立即返回;
<2>当子进程还没有停止运行或结束,则调用waitpid()函数的父进程则会被阻塞,暂停运行。
学习资料:
Linux中waitpid()函数的用法
https://blog.youkuaiyun.com/Roland_Sun/article/details/32084825
4.守护进程例子
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
void startDaemon() {
#ifndef _WIN32
static pid_t pid;
do {
pid = fork();
if (pid < 0) {
std::cout << "fork失败: pid=" << pid << std::endl;
//休眠1秒再试
sleep(1);
continue;
}
if (pid == 0) {
//子进程
return;
}
//父进程,监视子进程是否退出
std::cout << "启动子进程:pid=" << pid << std::endl;
signal(SIGINT, [](int) {
std::cout << "收到主动退出信号,关闭父进程与子进程" << std::endl;
kill(pid, SIGINT);
exit(0);
});
//父进程守护子进程,子进程崩了后,父进程再调一次fork
do {
int status = 0;
if (waitpid(pid, &status, 0) >= 0) {
std::cout << "子进程退出" << std::endl;
//休眠1秒再启动子进程
sleep(1);
break;
}
std::cout << "waitpid被中断:" << strerror(errno)<<std::endl;
} while (true);
} while (true);
#endif // _WIN32
}