守护进程制作

一、什么是守护进程

        守护进程,也就是通常所说的Daemon进程,是 Linux中的后台服务进程。它是一个生存期较长 的进程,通常独立于控制终端并且周期性的执行 某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。Linux系统有很多守护进程,大多数服务都是用 守护进程实现的。在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会被自动关闭。守护进程能够突破这种限制,它从被执行开始运转,直到整个系统关闭才会退出。如果想让某个进程不因为用户或终端或其他的变化而受到影响,就必须把这个进程变成一个守护进程。

二、查看常用的系统守护进程

        
父进程ID :      PPID
 进程ID :       PID
 进程组ID :     PGID
 会话期ID :     SID
 终端ID :       TTY
 终端进程组ID : TPGID
 状态 :         STAT
 用户 :         UID
 运行时间 :     TIME
 指令:          COMMAND

三、守护进程的制作流程


代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include<syslog.h>
void deamon_init(void);
int main(){
	deamon_init();
	openlog("opening",LOG_PID,LOG_DAEMON);
	int fd = open("1.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
	if(fd<0){
		syslog(LOG_ERR,"open error");
		exit(-1);
	    }
	char buf[50]="hello,this is deamo\n";
	while(1){
		sleep(3);
		write(fd,buf,strlen(buf));
		syslog(LOG_INFO,"%s",buf);
	}
	closelog();
	return 0;
}

void deamon_init(void){
	if(fork()!=0)
		exit(0);
	
	if(setsid()<0){
		perror("setsid:");
		exit(-1);
		
	}
	if(fork()!=0)
		exit(0);
	
	int i; 
	for(i = 0;i <= sysconf(_SC_OPEN_MAX);i++)
		close(i);
	chdir("/home/pm");
	umask(0);
	int fd = open("/dev/null",O_RDWR);
	dup(0);
	dup(0);
	
}

四、守护进程的编写

步骤:

1、创建子进程,杀死父进程:

        为了制作终端进程而做准备:组长进程无法成为终端 

//创建子进程,exit结束父进程,fork返回值是父进程pid且大于0    
 if(fork()!=0)
            exit(0);

2、设置当前子进程为一个终端:

        为了摆脱原来终端的控制关系

//设置子进程为终端,返回值为0没有参数      
  if(setsid()<0){
            perror("setsid");
            exit(-1);
        }   

3、创建子进程,杀死父进程 :

        彻底成为无法被进程管理和控制终端概念影响的守护进程雏形。

再次创建子进程杀死父进程,让新创建的子进程完全成为摆脱终端关系的进程 
   if(fork()!=0)
            exit(0); 
       //此时,守护进程雏形已完成,剩下的操作,子进程2(守护进程雏形)做

4、关闭所有文件描述符:

        为第七点做准备

 int i;
for(i=0;i<=sysconf(_SC_OPEN_MAX);i++)//for里面写表达式并不好:容易出现bug
       close(i);                     //不要再for里写任何表达式,引以为戒

5、更改执行目录:

        为避免守护进程影响源目录的删除和移动操作

//执行目录更改到根目录下,运行时记得添加sudo 
chdir("/");

6、修改掩码:

        为了让守护进程操作不被权限影响

 umask(0);

7、将标准输入,标准输出,标准错误输出重定向到设备NULL

        标准输入输出错误输出一开始都有对应的触发设备

//7>将标准输入、标准输出、标准错误输出重定向到设备null
      int fd=open("/dev/null",O_RDWR);
      dup(0);
      dup(0);
API学习:
                2>设置当前子进程为一个终端
                setsid 
                #include <sys/types.h>
                #include <unistd.h>
                pid_t setsid(void);
                功能: 
                        让执行该函数的进程,变成终端 
                        
                参数: 
                        无 
                        
                返回值: 
                        成功返回0 
                        失败返回-1,并设置错误码
                        
                4>关闭所有文件描述符
                    sysconf 
                    #include <unistd.h>
                    long sysconf(int name);
                    功能: 
                            找寻name选项的最大值 
                    参数:
                            name:_SC_OPEN_MAX -->找寻文件描述符的最大值
                            
                    返回值: 
                            成功找到选项的最大值 
                            失败返回-1,并设置错误码
                            
                5>更改执行目录
                    chdir
                    #include <unistd.h>
                    int chdir(const char *path);
                    功能: 
                           改变目录 
                           
                    参数: 
                           path:需要修改到的目录 

                    返回值: 
                           成功返回0 
                           失败返回-1,并设置错误码
                           
                6>修改掩码: 两种方式 
                    1>命令修改  --->适用于终端 
                    2>函数修改  --->适用于进程   ---!
                    umask   --》和命令同名
                    #include <sys/types.h>
                    #include <sys/stat.h>
                    mode_t umask(mode_t mask);
                    功能: 
                            修改某个进程当中操作的掩码
                            
                    参数: 
                            mask:掩码值
                            
                    返回值: 
                            成功返回掩码值
                            
                7>文件描述符重定向(复制)
                    dup 
                     #include <unistd.h>
                     int dup(int oldfd);
                     功能: 
                            以oldfd为模板,复制出一个新fd 
                            新fd所有的参数 都 继承 oldfd 
                            操作oldfd =  操作 新的fd
                     
                    参数;
                            oldfd:旧文件描述符 
                            
                    返回值: 
                            成功创建newfd并返回 newfd
                            失败返回-1,并设置错误码

        


五、守护进程日志记录

为什么做日志:

        守护进程它没有输入输出,也没有报错 ,我们无法对他进行相对简单的跟踪看,也无法得知其在我们背后做了什么操作 。所以我们:利用文件日志系统保存守护进程的操作信息

文件日志系统

 ubuntu的文件系统是:Ext4 
         Ext4:两种系统: 
                 1>文件日志系统         --->保留下来
                  2>时间回溯系统        ---->快照 
                                       
 系统日志:
                1>打开日志
                    openlog
                    #include <syslog.h>
                    void openlog(const char *ident, int option, int facility);
                    功能: 
                            打开日志 
                            
                    参数: 
                            ident:标签:char * 随意
                            option:选项 
                                LOG_PID :进程信息 
                                
                            facility:
                                LOG_DAEMON :守护进程 
                                                            
                2>写日志
                    syslog
                    #include <syslog.h>
                    void syslog(int priority, const char *format, ...);
                    功能: 
                            编写日志 
                            
                    参数: 
                            priority:优先级(报文)
                                LOG_ERR:出错
                                LOG_WARNING:警告 
                                LOG_INFO:正常
                                
                            format:类似printf 
                
                3>关闭日志 
                    closelog
                    #include <syslog.h>
                    void closelog(void);
                    功能: 
                            关闭日志
                            
                4>命令:查看日志 
                    vi /var/log/syslog

六、查看守护进程

ps -ajx 当TPGID显示-1时则表示为守护进程

运行程序:

 

 执行后显示:

 当关闭终端守护进程也不会关闭,而是会在后台运行:

 后台依旧有显示

 重启虚拟机会杀死我们写的守护进程:

 home目录下出现:守护进程中运行的写入程序。

 至此守护进程结束.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值