栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Linux实现守护进程创建

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux实现守护进程创建

目录

一、什么是进程

二、进程的分类

三、如何关闭进程

四、进程相关接口函数

1、fork()

2、exit()

3、wait()

4、exec()

五、守护进程的创建

1、进程组的概念

2、会话

3、创建

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

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

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

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

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

六、实例


一、什么是进程

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

二、进程的分类

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

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

按如下代码举例:

#include 
#include 
#include 
#include 
#include 
#define N 100

int main(int argc, char *argv[])
{
	while(1){
		printf("An");
		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
#include

pid_t fork(void);

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

2、exit()

#include


void exit(int status);

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

3、wait()

#include
#include

pid_t wait(int *wstatus);

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

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

4、exec()

#include

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

参数:
    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日志文件中每隔一秒,记录当前时间

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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("okn");
	//周期性执行的目标进程
	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文件生成,我们进入发现信息都已经写入了,说明我们的守护进程创建成功!!!

 

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1038982.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号