linux下编译C/C++文件需要安装的依赖
- yum -y install gcc gcc-c++ kernel-devel //安装gcc、c++编译器以及内核文件
编写守护进程的要点
- 忽略终端的I/O信号、STOP信号、sighup信号
- 创建子进程,结束父进程,使得子进程成为后台进程
- 建立一个新的进程组,在此进程组中,子进程成为首进程,以使该进程脱离所有终端
- 创建子进程,结束父进程,保证该进程不是进程组长,同时让该进程无法再打开一个新的终端
- 关闭打开的文件描述符
- 改变当前工作目录,使得进程不与任何文件系统联系
- 重设文件创建掩模
- 忽略SIGCHLD信号
用c实现的守护进程示例1-将程序变为守护进程
#include <signal.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
//#include<string.h>
int init_daemon(void)
{
pid_t pid;
int i;
/**
* 1)
* signal.h
* 忽略终端的I/O信号、STOP信号、sighup信号
* 防止守护进程在没有运行起来前受到干扰从而退出或挂起
*/
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGHUP, SIG_IGN);
/**
* 2)
* unistd.h stdlib.h
* 创建子进程
* 结束父进程,使得子进程成为后台进程
* 如果
*/
pid = fork();
if (pid > 0)
{
exit(0);
}
else if (pid < 0)
{
return -1;
}
/**
* 3)
* unistd.h
* 建立一个新的进程组
* 在此进程组中,子进程成为首进程,以使该进程脱离所有终端
*/
setsid();
/**
* 4)
* unistd.h stdlib.h
* 创建子进程
* 结束父进程,保证该进程不是进程组长,同时让该进程无法再打开一个新的终端
*/
pid = fork();
if (pid > 0)
{
exit(0);
}
else if (pid < 0)
{
return -1;
}
/**
* 5)
* sys/param.h unistd.h
* 关闭打开的文件描述符
* NOFILE 为 <sys/param.h> 的宏定义,意为文件描述符最大个数,不同系统有不同限制
*/
for (i = 0; i < NOFILE; i++) {
close(i);
}
/**
* 6)
* unistd.h
* 改变当前工作目录,使得进程不与任何文件系统联系
* 进程活动时,其工作目录所在的文件系统不能卸下,一般需要将工作目录改变到根目录
* 对于需要转储核心,写运行日志的进程可将工作目录改变到特定目录如 /tmp
*/
chdir("/");
/**
* 7)
* sys/types.h sys/stat.h
* 重设文件创建掩模
* 子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权
* 为防止这一点,使用unmask(0) 将屏蔽字清零
*/
umask(0);
/**
* 8)
* signal.h
* 忽略SIGCHLD信号
* 如果父进程不等待子进程结束,子进程将成为僵尸进程从而占用系统资源
* 如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能
* 在 Linux 下可以简单地将 SIGCHLD 信号的操作设为 SIG_IGN
*/
signal(SIGCHLD, SIG_IGN);
return 0;
}
int main()
{
init_daemon();
while (1)
{
system("date >> /tmp/test"); //做些事情
sleep(1);
}
return 0;
}
用c实现的守护进程示例2-守护进程接收信号并作出响应
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
int init_daemon(void)
{
pid_t pid;
int i;
/**
* 1)
* signal.h
* 忽略终端的I/O信号、STOP信号、sighup信号
* 防止守护进程在没有运行起来前受到干扰从而退出或挂起
*/
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGHUP, SIG_IGN);
/**
* 2)
* unistd.h stdlib.h
* 创建子进程
* 结束父进程,使得子进程成为后台进程
* 如果
*/
pid = fork();
if (pid > 0)
{
exit(0);
}
else if (pid < 0)
{
return -1;
}
/**
* 3)
* unistd.h
* 建立一个新的进程组
* 在此进程组中,子进程成为首进程,以使该进程脱离所有终端
*/
setsid();
/**
* 4)
* unistd.h stdlib.h
* 创建子进程
* 结束父进程,保证该进程不是进程组长,同时让该进程无法再打开一个新的终端
*/
pid = fork();
if (pid > 0)
{
exit(0);
}
else if (pid < 0)
{
return -1;
}
/**
* 5)
* sys/param.h unistd.h
* 关闭打开的文件描述符
* NOFILE 为 <sys/param.h> 的宏定义,意为文件描述符最大个数,不同系统有不同限制
*/
for (i = 0; i < NOFILE; i++)
{
close(i);
}
/**
* 6)
* unistd.h
* 改变当前工作目录,使得进程不与任何文件系统联系
* 进程活动时,其工作目录所在的文件系统不能卸下,一般需要将工作目录改变到根目录
* 对于需要转储核心,写运行日志的进程可将工作目录改变到特定目录如 /tmp
*/
chdir("/");
/**
* 7)
* sys/types.h sys/stat.h
* 重设文件创建掩模
* 子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权
* 为防止这一点,使用unmask(0) 将屏蔽字清零
*/
umask(0);
/**
* 8)
* signal.h
* 忽略SIGCHLD信号
* 如果父进程不等待子进程结束,子进程将成为僵尸进程从而占用系统资源
* 如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能
* 在 Linux 下可以简单地将 SIGCHLD 信号的操作设为 SIG_IGN
*/
signal(SIGCHLD, SIG_IGN);
return 0;
}
void signal_handler(int signo)
{
switch (signo)
{
case SIGINT:
system("date>>/tmp/test"); //做些事情
break;
}
}
int main()
{
init_daemon();
signal(SIGINT, signal_handler);
while (1)
{
sleep(1);
}
return 0;
}
停止守护进程
#首先执行以下命令查看我们守护进程的pid
ps aux | grep dameon
#找到pid后执行以下命令停止进程 xxx为pid值
kill xxx
原创文章,作者:witersen,如若转载,请注明出处:https://www.witersen.com