Linux实现守护进程创建

目录

一、什么是进程

二、进程的分类

三、如何关闭进程

四、进程相关接口函数

1、fork()

2、exit()

3、wait()

4、exec()

五、守护进程的创建

1、进程组的概念

2、会话

3、创建

(1)创建子进程,父进程退出,得到孤儿进程

(2)让子进程脱离原本会话

(3)修改当前工作路径(非必要,一般都会改)

(4)重设文件权限掩码(非必要,一般都会改)

(5)删除进程中所有的文件描述符(必须要操作)

六、实例


一、什么是进程

        进程:即正在运行的程序。

二、进程的分类

        前台进程:可以直接从当代终端使用ctrl+c退出的进程

        后台进程:只能使用kill杀死或者其父进程结束后才会结束的进程

按如下代码举例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#define N 100

int main(int argc, char *argv[])
{
	while(1){
		printf("A\n");
		sleep(2);
	}

	return 0;
}

 我们常规编译运行想要停止只需要ctrl+c即可退出,此时,我们这个正在运行的程序称为前台进程

 我们此时运行./a.out &(该命令可将前台进程转换为后台进程),这时候我们会发现继续使用ctrl+c无法将该程序杀死,这样的进程我们称其为后台进程。

三、如何关闭进程

        从第二点可以看出,对于前台进程,我们可以通过ctrl+c来进行关闭,那么,后台进程我们该如何杀死呢?

1、查看进程的PID(进程号)

指令:ps -ef

显示结果如下:

 

 找到我们要杀死的进程./a.outd的进程号为4727(每个人的都不一样)

接着我们输入以下命令:

kill -9 PID号

此处我的PID号为4727,所以我的输入为:

kill -9 4727

然后再刚才的终端就会显示如下结果:

此时说明我们的进程已经被杀死。同样,前台进程我们也可以使用这种方法来杀死。

四、进程相关接口函数

1、fork()

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

返回值:
    成功创建一个新的子进程,父进程返回子进程的PID号,子进程返回0
    失败父进程返回-1,没有子进程被创建

2、exit()

#include <stdlib.h>


void exit(int status);

参数:
    status:表示进程退出的状态

3、wait()

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *wstatus);

参数:
    wstatus:进程结束时,状态信息的首地址

返回值:
    成功返回结束子进程的pid号,失败返回-1

4、exec()

#include <unistd.h>

int execl(const char *pathname, const char *arg, .../* (char  *) NULL */);

参数:
    pathname:要执行程序的文件名
    arg:表示执行程序的命令行参数,命令行参数列表最终以NULL结尾
    
返回值:
    失败返回-1;

五、守护进程的创建

1、进程组的概念

        当用户执行了一个程序时,就相当于创建了一个进程组,跟该进程具有亲缘关系的所有进程都属于该进程组。

2、会话

        当用户打开一个终端时,就创建了一个会话,一个会话由一个或者多个进程组组成,一旦终端关闭,该会话中所有进程组中的进程全部结束。

3、创建

(1)创建子进程,父进程退出,得到孤儿进程

fork()函数打开,exit()退出父进程

(2)让子进程脱离原本会话

setsid()

(3)修改当前工作路径(非必要,一般都会改)

chdir():修改当前工作路径


int chdir(const char *path);

path一般为“ / ”或者“ /tmp ”

(4)重设文件权限掩码(非必要,一般都会改)

umask(0);

(5)删除进程中所有的文件描述符(必须要操作)

getdtablesize()//获取最大的文件描述符
    
int i = 0;
for(i = 0; i < getdtablesize; i++){
    close(i);
}

while(1)
{
    //周期性的需要执行的进程
}

六、实例

        创建一个守护进程,在time.log日志文件中每隔一秒,记录当前时间

代码如下:

/*===============================================================
 *   Copyright (C) 2022 All rights reserved.
 *   
 *   文件名称:daemon.c
 *   创 建 者:QiuCC
 *   创建日期:2022年08月08日m *now_time;

 *   描    述:
 *
 *   更新日志:
 *
 ================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#define N 100

int main(int argc, char *argv[])
{
	time_t now_sec;
	struct tm *now_time;

	int i, ret;
	pid_t daemon_pid = -1;

	//创建子进程
	daemon_pid = fork();
	if(daemon_pid < 0){
		perror("Create daemon_pid");
		return -1;
	}

	//判断父子进程
	if(daemon_pid > 0){
		exit(0);//杀死父进程,得到孤儿进程
	}

	setsid();//让子进程脱离原本回话
	chdir("/tmp");//修改当前工作路径,之后打开文件必须给绝对路径,不然会写到/tmp下的time.log中
	umask(0);//重设文件权限掩码

	//删除进程中所有的文件描述符
	for(i = 0; i < getdtablesize(); i++){
		close(i);
	}
	printf("ok\n");
	//周期性执行的目标进程
	while(1){
		time(&now_sec);
		now_time = localtime(&now_sec);

		FILE *fp = fopen("/home/qcc/Desktop/learn/04level/daemon/time.log", "a+");
		if(NULL == fp){
			perror("fopen");
			exit(-1);
		}


		fprintf(fp, "%d年%d月%d日%d时%d分%d秒\n", now_time->tm_year+1900, now_time->tm_mon+1, now_time->tm_mday, now_time->tm_hour, now_time->tm_min, now_time->tm_sec);
	
		//fflush(fp);
		fclose(fp);

		sleep(1);
	}


	return 0;
}

接下来我们运行以上代码

 此时由于是后台进程,我们无法在前台看到执行过程,所以我们使用ps -ef查看进程号

此时我们可以看到我们的守护进程正在后台运行,并且PID号为4938,我们kill ./a.out

接着我们ls查看当前目录,发现我们之前没有创建的time.log文件生成,我们进入发现信息都已经写入了,说明我们的守护进程创建成功!!!

 

好的,以上就是本期内容,欢迎大家参考指正!!!

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玖尾猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值