守护进程-解析
Posted hntea-hong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了守护进程-解析相关的知识,希望对你有一定的参考价值。
守护进程-解析
1.概念:守护进程也称为精灵进程,是生存期较长的一种进程
a) 系统自举启动,系统关闭时终止
b) 没有控制终端,在后台运行
2.终端查看守护进程
a) ps -axj
i. -a 显示由其他用户所拥有的进程状态
ii. -x 显示没哟控制终端的进程状态
iii. -j 显示与作业有关的信息
b) 显示解析
i. PPID:父进程
ii. PID:进程
iii. PGID:进程组
iv. SID:会话ID
v. TTY:终端名称
vi. TPGID:终端进程组ID
vii. UID:用户ID
viii. COMMAND:命令字符串
3.父进程ID为0的各进程通常是内核进程,作为系统自举过程的一部分而启动
4.LINUX下的守护进程
a) keventd:为在内核中运行计划执行的函数提供进程上下文
b) kapmd:对计算机系统提供高级电源管理支持
c) kswapd:页面调出守护进程
d) bdflush和kupdated:将高速缓存中的数据冲洗到磁盘上
e) Portmap:端口映射进程,提供远程过程调用
f) ...
5.编程规则
a) 调用umask(0) : 将文件模式创建屏蔽字设置为0
b) 调用fork():创建子进程,
i. 继承父进程的进程组ID,但具有一个新的进程ID
ii. 保证子进程不是一个进程组的组长进程(进程ID与进程组ID相等)
c) 调用exit(0):退出父进程
d) 调用setsid():创建一个新会话(session)是一个或多个进程组的集合
i. 该进程变成新会话首进程,此时该进程是新会话中的唯一进程
ii. 该进程将成为一个新的进程组的组长进程
iii. 该进程没有控制终端
e) 调用 chdir(“/”)将当前工作目录更改为 “根目录”
f) 关闭不再需要的文件描述符
i. 使守护进程不再持有父进程继承过来的某些文件描述符
守护进程惯例
1.若守护进程使用锁文件,该文件通常放在/var/run目录中
a) 锁文件命名格式:守护进程名/服务名.pid
2.若支持配置选项
a) 配置文件通常放在 /etc目录,命名格式 name.conf
3.守护进程可用命令行启动,但是通常它们是由系统初始化脚本
a) /etc/rc*
b) /etc/init.d/*
4.守护进程终止,应当自动的从新启动
a) /etc/inittab中为该守护进程包括 _respawn记录项,这样init就将重启该守护进程
守护进程出错记录
1.用户进程(守护进程)大多调用函数
a) syslog(3):产生日志消息
i. 使消息发送至UNIX域数据报套接字 /dev/log
b) syslogd 守护进程读取三种格式的日志消息
i. UNIX域数据报套接字
ii. 因特网域数据报套接字
iii. 内核例程
iv. 启动过程
1. 读取配置文件 /etc/syslog.conf :该文件决定不同种类的消息送往何处
v. 接口函数
1. openlog
2. syslog
3. closelog
4. setlogmask
vi. 问题来了,输出的消息在哪个文件呢?
2.syslog 日志输出文件程序设计
a) 寻找配置文件 /etc/rsyslog.conf 配置文件
b) 在配置文件最后添加自己用户程序的调试文件
i. 格式如下
ii. 消息来源.优先级 /日志文件所在路径
iii. 消息来源-由syslog(第一个参数决定)
iv. 优先级同上
1. 例如 syslog(LOG_DAEMON|LOG_DEBUG,“.........”,...);
2. 配置文件修改:
a) daemon.debug /var/log/文件名
3. 配置文件生效
a) 在终端输入:service syslog restart
4. 执行应用程序后查看日志
v. 具体/usr/include/sys/syslog.h文件中有相关的标志说明
例子-设计云公交刷卡器守护进程
1.任务设计:
a) 系统自启动
b) 监测刷卡动作
c) 读取数据并以固定格式写入指定文件
d) 写入前清空文件数据
****************************************************
作者:hntea
函数功能:公交打卡机数据采集
日期:2016/3/1
****************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/times.h>
#include <sys/resource.h>
#define CONFIG_DEBUG 0 /*打印函数开关*/
#ifdef CONFIG_DEBUG
#define BUSCARD_DBG(formate...) do \\
if(CONFIG_DEBUG) \\
printf(formate); \\
while(0)
#endif
#define OUT_FILE_NAME "/hntea/bus301.txt"
#define BAUD_RATE 9600
#define DEV_PATH "/dev/ttyUSB0"
extern int openTermio(const char* devPath);
extern int termiosetup(int fd,int nSpeed, int nBits, char nEvent, int nStop);
typedef struct ibuscard
unsigned char card_nm_first; /*第一个卡号,触发条件*/
unsigned char card_nm[3]; /*磁卡号码*/
unsigned int balance; /*余额*/
unsigned int expens_money; /*票价*/
unsigned char expens_num; /*消费次数*/
const char* out_file_name; /*数据输出文件名*/
const char* out_path; /*数据输出路径*/
const char* ttyusb_port; /*设备挂载端口*/
unsigned int baud_rate; /*设备波特率*/
IBUS_CARD;
IBUS_CARD* card_data; /*全局结构--需要分配内存*/
struct tm* local_time; /*全局结构--需要分配内存*/
void delay(int x,int y)
int i,j;
for(i=x;i>0;i--)
for(j=y;j>0;j--);
/***************************************************/
/*
函数名称:daemoinit()
函数功能:守护进程初始化
参数说明:
*/
/***************************************************/
void daemoinit(void)
int i = 0;
pid_t pid = 0;
struct rlimit r1;
/*创建守护进程*/
/*1.屏蔽文件模式*/
umask(0);
/*2.创建子进程*/
if( (pid=fork()) < 0)
BUSCARD_DBG("Create chile process err!\\n");
exit(1); /*无法创建直接退出*/
else if(pid != 0)
/*3.退出父进程*/
BUSCARD_DBG("Create chile process success!\\n");
exit(0);
/*4.退出终端,创建新会话*/
setsid();
/*5.切换工作目录*/
chdir("/");
/*6.1 获取文件最大描述符*/
if(getrlimit(RLIMIT_NOFILE,&r1) < 0)
BUSCARD_DBG("get RLIMIT_NOFILE err!\\n");
return ;
/*6.2 关闭所有文件描述符*/
for(i=0;i<r1.rlim_max;i++)
close(i);
/**************************************************
函数名称:getTime
函数功能:时间显示格式化 年-月-日 时:分:秒:毫秒
参数说明:
**************************************************/
static struct tm* getTime(void)
unsigned char* buf ;
time_t timeval;
struct tm *localtime;
int fd;
/*获取当前时间和日期*/
timeval = time(&timeval);
/*时间分割*/
localtime = gmtime(&timeval);
/*格式化打印*/
#if 0
printf("【%d-%d-%d %d:%d:%d】\\n",\\
localtime->tm_year+1900,\\
localtime->tm_mon, \\
localtime->tm_mday, \\
localtime->tm_hour, \\
localtime->tm_min, \\
localtime->tm_sec \\
);
#endif
return localtime;
/*****************************************************/
/*
函数名称:readDataFromBusCard()
函数功能:读取磁卡数据
参数说明:
fd:文件语句柄
bus_card:将读到的数据存放到该数据结构中并作为返回值
*/
/*****************************************************/
static struct IBUS_CARD* readDataFromBusCard(int fd,IBUS_CARD* card_data)
int ret = 0;
unsigned char first_char=0;
int read_times=1,i=0; /*只读取一次*/
unsigned char tem[6];
/*清空数组*/
bzero(tem,6);
while(1)
/*终端数据录入太慢,无法一次性全部读取,要一次性全读取需要一定延时*/
while(!(ret = (read(fd,&first_char,1)))); /*等待数据录入*/
usleep(7000);
while(!(ret = (read(fd,tem,7)))); /*等待数据录入*/
/*跳过空数据,无数据在此等待*/
if((tem[0]>0)&&read_times)
/*fill data*/
read_times=0;
card_data->card_nm_first = first_char;
memcpy(card_data->card_nm,tem,3); /*fill card_num,填充时还有要算上分割符号*/
card_data->balance = tem[3]; /*最大只能显示到256*/
card_data->expens_money = tem[4]; /*fill expens_money*/
card_data->expens_num = tem[5]; /*fill expend_num*/
#if 0
printf("【carnum:%x-%x-%x-%x balance %d expensmoney %d exxpensnumber %d 】\\n",
card_data->card_nm_first,
card_data->card_nm[0],
card_data->card_nm[1],
card_data->card_nm[2],
card_data->balance,
card_data->expens_money,
card_data->expens_num
);
#endif
break;
return card_data;
/**************************************************
函数名称:wtiteFormate
函数功能:时间显示格式化 年-月-日 时:分:秒:毫秒 aa bb cc dd ee ff gg
参数说明:
localtime:当地时间结构体
card_data:要格式写入的卡数据
**************************************************/
void wtiteFormate(struct tm *localtime,IBUS_CARD* card_data)
/*标准I/O操作*/
/*创建标准I/O流 对象*/
FILE *fp;
/*以可读可写方式打开流,文件不存在时自动创建*/
fp = fopen(OUT_FILE_NAME, "w+");
fprintf(fp,"【%d-%d-%d %d:%d:%d】%x %x %x %x %x %x %x\\n",\\
localtime->tm_year+1900,\\
localtime->tm_mon, \\
localtime->tm_mday, \\
localtime->tm_hour, \\
localtime->tm_min, \\
localtime->tm_sec, \\
card_data->card_nm_first, \\
card_data->card_nm[0], \\
card_data->card_nm[1], \\
card_data->card_nm[2], \\
card_data->balance, \\
card_data->expens_money,\\
card_data->expens_num
);
/*关闭流*/
fclose(fp);
/***************************************************/
/*
函数名称:daemowork()
函数功能:守护进程任务
参数说明:
*/
/***************************************************/
void daemowork(int fd,IBUS_CARD* card_data,struct tm* local_time)
/*守护进程的工作*/
#if 0
card_data = readDataFromBusCard(fd,card_data); /*读取卡数据*/
local_time = getTime(); /*获取时间*/
wtiteFormate(local_time,card_data); /*格式化写入文件*/
#endif
/***************************************************/
/* 主函数
功能:打开串口,设置串口属性,在后台处理数据(守护进程)
参数:
argc:命令个数---> 执行文件本身算一个命令,放在 argv[0] 中
argv: 命令参数
int main(int argc,const char* argv[])
*/
/***************************************************/
int main(void)
int termio_fd = 0;
int ret=0;
/*为结构体分配内存*/
card_data = malloc(sizeof(IBUS_CARD));
local_time = malloc(sizeof(struct tm));
/*1.创建守护进程*/
daemoinit();
/*2初始化串口*/
/*2.1.打开终端设备文件设备文件*/
termio_fd = openTermio(DEV_PATH);
/*2.2.设置串口*/
ret = termioSetup(termio_fd,9600,8,'N',1);
while(1)
card_data = readDataFromBusCard(termio_fd,card_data); /*读取卡数据*/
local_time = getTime(); /*获取时间*/
wtiteFormate(local_time,card_data); /*格式化写入文件*/
free(card_data);
free(local_time);
return 0;
以上是关于守护进程-解析的主要内容,如果未能解决你的问题,请参考以下文章
RegEX - 查找Track 1和Track 2子串的磁卡字符串
Android 进阶——Framework 核心之Binder对象管理者 Service Manager 守护进程及其自身代理对象详解