lv5 嵌入式开发-3 守护进程

2023-09-21 13:14:24

目录

1 守护进程的概念

1.1 相关概念

1.2 举例

1.3 函数介绍

2 守护进程的实现

2.1 简单创建

2.2 守护进程创建

2.3 实例


掌握:守护进程特点、会话、控制终端、创建守护进程

1 守护进程的概念

守护进程又叫精灵进程(Daemon Process),它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

  • 守护进程(Daemon Process)是Linux三种进程类型之一
  • 是 Linux 中的后台服务进程
  • 是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件

无法通过bg、fg切换至前台后台,它是一个后台进程。

脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。

1.1 相关概念

进程组(Process Group): 进程集合,每个进程组有一个组长(Leader),其进程 ID 就是该进程组 ID。(如fork的父与子即进程组)

会话(Session): 进程组集合,每个会话有一个组长,其进程 ID 就是该会话组 ID。(即终端)

控制终端(Controlling Terminal):每个会话可以有一个单独的控制终端,与控制终端连接的 Leader 就是控制进程(Controlling Process)。

1.2 举例

http 服务的守护进程叫 httpd,mysql 服务的守护进程叫 mysqld。

1.3 函数介绍

setsid函数:

pid_t setsid(void);

成功:返回调用进程的会话ID;失败:-1,设置errno。

调用了setsid函数的进程,既是新的会长,也是新的组长

getsid函数:

pid_t getsid(pid_t pid)
  • 成功:返回调用进程的会话ID;失败:-1,设置errno

-pid为0表示察看当前进程session ID

-ps ajx命令查看系统中的进程。参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与作业控制相关的信息。

-组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。

getpid:pid_t getpid(void);       获取进程id

getpgid:pid_t getpgid(pid_t pid);   获取进程组id

2 守护进程的实现

2.1 简单创建

更简便地创建守护进程: nohup 命令

nohup  xxxx  &

2.2 守护进程创建

第一步

创建子进程,父进程退出

if (fork() > 0){
    exit(0);
}

子进程变成孤儿进程,被init进程收养  

子进程在后台运行

第二步

子进程创建新会话

if(setsid() < 0)  
{
    exit(-1);
}

子进程成为新的会话组长  

子进程脱离原先的终端

第三步(非必须)

更改当前工作目录

chdir(“/”);
chdir(“/tmp”);

守护进程一直在后台运行,其工作目录不能被卸载   重新设定当前工作目录cwd

第四步(非必须,如果不会新创建文件)

重设文件权限掩码

if(umask(0) < 0)  
{
    exit(-1);
}

文件权限掩码设置为0  

只影响当前进程

第五步

关闭打开的文件描述符

int  i;
for(i=0; i<3; i++) 
{
    close(i);
}

关闭所有从父进程继承的打开文件  

已脱离终端,stdin / stdout / stderr无法再使用

2.3 实例

编写一个程序,实现创建子进程,父进程退出,演示后台程序

方式一:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char * argv[])
{
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		perror("fork");
		return -1;
	}
	else if(pid == 0)
	{
		printf("I am a deamon\n");  //子进程
		sleep(100);
	}
	else
	{
		exit(0);                    //父进程退出
	}

}

编译后运行,不管是按ctrl+c,或者查看前台进程都不会使得mydae结束,并且查看它的父进程是init,如果想接触需要使用kill命令,至此完成守护进程的第一步,与前台终端无关,如果不把父进程结束,它还是个前台进程。

方式二:

不用exit,执行程序,此时查看进程状态,父进程和子进程都存在,ctrl+c,父子进程同时结束。

使用nohup 【执行程序】 &的方式,此时按ctrl+c,进程都在后台运行。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char * argv[])
{
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		perror("fork");
		return -1;
	}
	else if(pid == 0)
	{
		printf("I am a deamon\n");
		sleep(10);
	}
	else
	{
		sleep(10);
	}

}


linux@linux:~$ ps -ef|grep a.out
linux     5690  2865  0 12:08 pts/0    00:00:00 ./a.out
linux     5691  5690  0 12:08 pts/0    00:00:00 ./a.out
linux     5695  5164  0 12:08 pts/6    00:00:00 grep --color=auto a.out
linux@linux:~$ ps -ef|grep a.out  //按下ctrl+c
linux     5697  5164  0 12:08 pts/6    00:00:00 grep --color=auto a.out
linux@linux:~$ nohup ./a.out &
linux@linux:~$ ps -ef|grep a.out
linux     5777  2865  0 12:18 pts/0    00:00:00 ./a.out
linux     5778  5777  0 12:18 pts/0    00:00:00 ./a.out
linux     5780  5164  0 12:18 pts/6    00:00:00 grep --color=auto a.out

方法三:

根据2.2步骤创建守护进程

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(){
  pid_t pid;
  pid = fork();
  
  //1 创建子进程,父进程退出
  if(pid<0){
    perror("fork");
    return 0;

  }else if(pid>0){
    exit(0);
    //sleep(100);
  }
  printf("I am a deamon\n");

  printf("sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));

  //2 子进程创建新会话
  if(setsid()<0){
    perror("setsid");
    exit(0);
  }  

  //创建后,sid 、pgid以是自己新创建的了。
  printf("after sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));
  
  //3 更改当前工作目录,这里创建到了根目录
  chdir("/");

  //4 重设文件权限掩码,文件权限掩码设置为0,只影响当前进程
  if(umask(0)<0){
    perror("unmask");
    exit(0);
  }
  
  //关闭打开的文件描述符
  close(0);
  close(1);
  close(2);
  printf("after close \n");  



  sleep(100);

}



//运行结果
linux@linux:~/Desktop$ ./a.out 
Father pid exit
linux@linux:~/Desktop$ Im a Deamon
sid=5164,pid=7739,pgid=7738
after sid=7739,pid=7739,pgid=7739
^C
linux@linux:~/Desktop$ ps -ef|grep "a.out"
linux     7739  2102  0 00:42 ?        00:00:00 ./a.out
linux     7761  5164  0 00:44 pts/6    00:00:00 grep --color=auto a.out
linux@linux:~/Desktop$ 

含义和解释:

  • SID(Session ID):会话标识符,用于标识一个会话(session)。在多用户操作系统中,一个会话可以包含多个进程组(process group),而一个进程组又可以包含多个进程。会话标识符用于区分不同的会话。

  • PID(Process ID):进程标识符,用于唯一标识一个进程。每个运行的进程都有一个独立的进程标识符。进程标识符通常从1开始自增,直到达到系统的最大限制。

  • PGID(Process Group ID):进程组标识符,用于将一组相关联的进程归为同一进程组。进程组的创建可以通过系统调用(如setpgid)来完成。PGID可以与PID相同,也可以不同。

这些标识符在进程管理和控制方面起到重要作用,例如确定进程归属关系、进程间通信、信号传递等。

更多推荐

为什么现在的LLM都是Decoder only的架构?

LLM是“LargeLanguageModel”的简写,目前一般指百亿参数以上的语言模型,主要面向文本生成任务。跟小尺度模型(10亿或以内量级)的“百花齐放”不同,目前LLM的一个现状是Decoder-only架构的研究居多,像OpenAI一直坚持Decoder-only的GPT系列就不说了,即便是Google这样的并

亚马逊推广计划是什么?亚马逊新手推广计划怎么做——站斧浏览器

亚马逊推广计划是什么?亚马逊新品推广是亚马逊运营的重要一环,需要把握好关键时间截单的节奏,如果是要等上架之后再来准备营销计划,是很难把握住关键时间节点的,而且容易措手不及,后期的推广也会很吃力。首先,了解目标受众是推广的关键。在进行任何推广活动之前,我们必须明确自己的产品究竟适合哪些人群,并且要深入了解他们的需求和购买

【Linux】网络设置之基础操作命令详解

大家好,本篇文章主要讲的是Linux网络设置之基础操作命令详解,感兴趣的同学快来看一看吧,对你有用的话记得收藏起来,方便下次浏览查看网络配置查看网络接口信息—ifconfig查看活动的网络接口设备1、ifconfig网卡名称查看指定的网络接口设备1、ifconfig网卡名称#可查看所有存在的网络接口,包括未激活的​补充

接口自动化测试之HTTP协议详解

协议简单理解,计算机与计算机之间的通讯语言就叫做协议,不同的计算机之间只有使用相同的协议才能通信。所以网络协议就是为计算机网络中进行数据交换而建立的规则,标准或约定的集合。OSI模型1978年国际化标准组织提出了“开放系统互联网参考模型”,即著名的OSI模型。它将计算机网络体系结构的通信协议划分为7层,自上而下分别是:

循环神经网络

循环神经网络(RecurrentNeuralNetworks,RNN)是一种强大的深度学习模型,适用于处理序列数据,如时间序列、文本、语音等。RNN具有记忆能力,可以捕捉序列中的时间依赖关系,并广泛应用于自然语言处理、语音识别、推荐系统等领域。本文将介绍RNN的基本原理、模型结构、训练方法以及应用案例。一、循环神经网络

百度地图 缩放组件

<!DOCTYPEhtml><html><head><metacharset="utf-8"/><metaname="viewport"content="initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/><title>地铁图

EFLAGS寄存器与JCC指令

EFLAGS寄存器EFLAGS寄存器有32位,EFLAGS寄存器的标志位可以通过各种指令进行操作和判断,例如条件分支指令、算术指令和控制指令等。程序可以根据标志位的值来进行条件判断和控制流程,从而实现不同的逻辑和功能。EFLAGS寄存器的各个位和标志位含义如下:CF(CarryFlag):进/借位标志位。用于表示某些算

java学习平台springboot004

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路,向着优秀程序员前行!🍅更多优质项目👇🏻👇🏻可点击下方获取🍅文章底部或评论区获取🍅Java项目精品实

【SpringCloud微服务全家桶学习笔记-服务调用Ribbon/openFeign】

SpringCloud微服务全家桶学习笔记内容:SpringCloud+SpringCloudalibaba技术栈:Java8+maven+git,github+Nginx+RabbitMQ+SpringBoot2.0仓库:链接服务调用Ribbon是什么?Ribbon是Netflix发布的开源项目,主要功能是提供客户端

【LeetCode每日一题合集】2023.9.11-2023.9.17(⭐反悔贪心&拓扑排序&Floyd)

文章目录630.课程表III解法——反悔贪心⭐⭐⭐⭐⭐1462.课程表IV⭐解法1——拓扑排序预处理解法2——Floyd算法判断是否存在路径2596.检查骑士巡视方案(方向模拟)1222.可以攻击国王的皇后(方向模拟)LCP50.宝石补给(简单模拟)198.打家劫舍(经典线性DP)213.打家劫舍II(循环打家劫舍)代

成功入选 2023 谷歌出海创业加速器,Tapdata 乘势远航

9月6日,2023Google开发者大会的收官之行于上海拉开帷幕。会间,官方正式公布了最新一期谷歌出海创业加速器入营名单,Tapdata成功入选:长期以来,Google开发者大会为开发者提供了一个独一无二的学习和合作机会,这是一场汇聚全球创新者的聚会,鼓励创新思维。从中能够深入了解最新的技术趋势、工具和平台,与行业内顶

热文推荐