【linux高级程序设计】(第八章)进程管理与程序开发 5
守候进程
启动方式:
- 在系统启动时由/etc/rd.d目录下的启动脚本启动
- 利用inetd超级服务器启动
- 有cron命令定时启动,以及在终端用nohup命令启动
守护进程编程要点
(1)屏蔽有关控制终端操作的信号,防止守护进程正常启动之前,控制终端受到干扰退出或挂起。
for(i = ; i <= ; i++)
signal(SIGTTOU, SIG_IGN); //忽略所有可以忽略的信号,STGSTOP和SIGKILL不能忽略
(2)在后台运行,为了避免挂起控制终端。方法在进程中创建子进程,并使父进程终止。
if(pid = fork())
exit(); //父进程结束,子进程继续
(3)脱离控制终端和进程组。用setsid()使子进程成为新的会话组长,彻底脱离从父进程继承下来的控制终端的影响
setsid();
(4)禁止进程重新打开控制终端。只有会话组长能够打开终端,再创建一个子进程,并让父进程退出,这样子进程就不是会话组长了。
if(pid = fork())
exit(); //父进程结束,子进程继续
(5)关闭打开的文件描述符。一般,不需要从父进程那继承来的文件描述符。
#define NOFILE 256 //不同系统有不同限制
for(i = ; i < NOFILE; i++) //关闭打开的文件描述符
close(i);
(6)改变当前工作目录。进程活动时,其工作目录所在的文件系统不能卸载。故需要将守候进程的工作目录改变到合适的目录
chdir("/tem");
(7)重设文件创建掩码。防止修改守护进程所创建文件的存储权限
umask();
(8)处理SIGCHLD信号(子进程退出信号)。让系统帮助回收僵死进程资源
signal(SIGCHLD, SIG_IGN);
守候进程两种写日志信息的方式
(1)进程直接与日志文件建立联系,即open一个文件,然后write写文件
(2)使用日志守候进程syslogd
void openlog (__const char *__ident, int __option, int __facility):打开当前程序与日志守候进程之间的联系。
参数1:要向每个消息加入的字符串,一般为当前进程名
参数2:描述已打开选项
参数3:消息类型,决定将消息写入那个日志文件中
void closelog(void):关闭与日志守候进程的联系
void syslog (int __pri, __const char * __fmt, ...) :写一条日志信息
参数1:决定日志级别 0系统不可用,1必须立刻报告的 2冲突 3错误 4警告 5普通担忧特殊标识 6消息 7调度级
参数2:日志输出格式,类似printf的第二个参数
int setlogmask (int __mask) :设置当前进程syslog()函数输出消息的默认优先级
守候进程例子
#include<unistd.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/syslog.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h> int init_daemon(const char *pname, int facility)
{
int pid;
int i;
signal(SIGTTOU, SIG_IGN); //处理可能的终端信号
signal(SIGTTIN, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGHUP, SIG_IGN); if(pid = fork()) //创建子进程,父进程退出
exit(EXIT_SUCCESS);
else if(pid < )
{
perror("fork");
exit(EXIT_FAILURE);
}
setsid(); //设置新会话组长
if(pid = fork()) //创建子进程,父进程退出
exit(EXIT_SUCCESS);
else if(pid < )
{
perror("fork");
exit(EXIT_FAILURE);
}
for(i = ; i < NOFILE; ++i) //关闭父进程打开的文件描述符
close(i);
open("/dev/null", O_RDONLY); //对标准输入输出全部重定向到/dev/null
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR); chdir("/tmp"); //修改主目录
umask(); //重新设置文件掩码
signal(SIGCHLD, SIG_IGN); //处理子进程退出
openlog(pname, LOG_PID, facility); //与守候进程建立联系,加上进程号,文件名
return;
} int main(int argc, char * argv[])
{
FILE *fp;
time_t ticks;
init_daemon(argv[], LOG_KERN); //执行守候进程函数
while()
{
sleep();
ticks = time(NULL); //获取当前时间
syslog(LOG_INFO, "%s", asctime(localtime(&ticks))); //写日志信息
}
}
可以看到,守候进程在后台运行
运行后我找不到日志写哪了?
还有很奇怪的一点,之后每次我用ps aux|grep Daemon_exp 进程号都会加2 ?
最新文章
- Visual Studio Code预览版Ver 0.3.0试用体验
- VTK初学一,动画加AVI录制终于做出来了
- iOS柱状图的绘制
- caller和callee
- Android模拟器配置选项说明
- linux内核学习之三:linux中的";32位";与";64位";
- Android 定义重名权限问题
- python 使用paramiko模块上传本地文件到ssh
- 关于Web Audio API的入门
- UISegmentedControl在Swift中的使用
- 洗礼灵魂,修炼python(42)--巩固篇—type内置函数与类的千丝万缕关系
- C语言复制文件的两种简单的方法【从根本解决问题】
- urllib.parse.quote
- TeamViewer 的早期版本下载
- P3572 [POI2014]PTA-Little Bird
- OpenWrt设置访客网络Guest Wi-Fi
- 安装pygame for Python3.5
- Thrift-RPC client in Flume
- erlang的dict和maps模块
- BZOJ3065 带插入区间K小值 || 洛谷P4278