进程间关系和守护进程

这篇博客深入探讨了进程组、作业和会话的概念,解释了它们在操作系统中的作用。重点介绍了如何通过shell进行作业控制,包括前台和后台作业的管理,并详细阐述了守护进程的特性及其在系统服务中的应用。通过示例代码解释了如何创建守护进程,强调了setsid函数的关键作用。
摘要由CSDN通过智能技术生成

进程组/作业/会话

1.进程组

每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或多个进程的集合.通常,它们与同一作业相关联,可以接收来自同一终端的各种信号.

每一个进程组有一个唯一的进程组ID,每一个进程组都可以有一个组长进程.组长进程的标识是进程ID与进程组ID相同.组长进程可以创建一个进程组,这个进程组中 只要有一个进程 存在,这个进程组就存在。与组长进程是否存在无关.



2.作业

sheel分前后台来控制的不是进程而是作业,或者进程组.

当命令行执行一个程序的时候,就形成了一个作业,这个作业可以有一个进程,也可以有多个进程。

一个前台作业可以有多个进程组成,一个后台作业也可以有多个进程组成,

sheel可以运行一个前台作业或者多个后台作业.------作业控制

为什么shell只能运行一个前台作业?

当我们运行一个作业时,shell就被提到了后台,这时的shell不能接受我们的指令并解析执行了,但是如果后台作业退出了,shell就会被提到前台

@@@@作业与进程组的区别@@@@--------如果作业中某个进程又创建了子进程,则子进程不属于作业.属于进程组,一旦作业运行结束,sheel就把自己提到前台(子进程还在,可是子进程不属于作业),如果原来的前台进程还在,(如果这个子进程还没终止),它就会自动变为后台进程组.

  1 #include<stdio.h>
  2 #include<unistd.h>                                                                                                               
  3 int main(){
  4    pid_t id = fork();
  5    if(id<0){
  6    perror("fork");
  7    return 1;
  8    }
  9    else if(id==0){
 10    //子进程
 11    while(1){
 12       printf("child(%d)# i am run!\n",getpid());
 13       sleep(1);
 14      }
 15    }
 16    else{
 17      //父进程
 18      int i=5;
 19      while(i){
 20      printf("parent(%d)# i am going to dead .... %d\n",getpid(),i--);
 21      sleep(1);
 22      }
 23    }
 24    return 0;
 25 }  


一旦作业运行结束,shlle就 被提到前台(子进程还在,可是子进程不属于作业),如果原来的前台进程还在(如果这个子进程还存在),它自动变为后台的进程.

在前台新起作业,shell是无法运行的,因为他被提到了后台,但是如果前台进程退出,shell就又被提到前台,所以就可以继续输入.


 jobs命令可以查看当前有哪些作业,fg命令可以把作业提到前台运行 ,如果该作业处于正在运行状态,则提至前台运行,如果该作业处于停止状态,则给进程组的每一个进程发SIGCONT信号使它继续运行,ctrl+z则向所有前台进程(前台作业)发SIGTSTR信号,该信号默认动作是使进程停止,该作业继续以后台形式存在.ctrl+c则杀掉整个作业

3.会话

会话(Session)是一个或者多个进程组的集合,一个会话可以有一个控制终端,建立与终端连接的会话首进程称为控制进程,一个会话中的几个进程可被分为一个前台进程组以及多个后台进程组,所以一个会话中应该包括控制进程(会话首进程),一个前台进程组和任意后台进程组.


守护进程

守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。比如,ftp服务器,ssh服务器,Web服务器httpd等。同时,守护进程完成许多系统任务。比如,作业规划进程crond等。

Linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程(守护进程)不受用户登录注销的影响,它们一直在运行着。这种进程有一个名称叫守护进程(Daemon)。


.......还有很多

凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。

在COMMAND一列用[]括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行, 通常采用以k开头的名字,表示Kernel。

init进程我们已经很熟悉了,udevd负责维护/dev目录下的 设备文件,acpid负责电源管理,syslogd负责维护/var/log下的日志文件.

可以看出,守护进程通常采用d结尾的名字,表示Daemon

创建守护进程

创建守护进程最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader。

#include <unistd.h>
pid_t setsid(void);
该函数调用成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。

注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进 程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进程组中,进程组的Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子进程中调用setsid就不会有问题了。
成功调用该函数的结果是:
创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,

代码:

  1 #include<unistd.h>                                                                                                               
  2 #include<signal.h>
  3 #include<stdlib.h>
  4 #include<stdio.h>
  5 #include<fcntl.h>
  6 #include<sys/stat.h>
  7 void mydaemon(void){
  8  int i;
  9  int fd0;
 10  pid_t pid;
 11  struct sigaction sa;
 12  //Linux中信号相关的一个结构体struct sigaction主要在sigaction信号安装和sigqueue信号发送时会用到
 13  //该结构位于/usr/include/bits/sigaction.h
 14  umask(0);//调用umask将命令模式创建屏蔽字设置0
 15  if(pid=fork()<0){
 16     perror("fork");
 17  }
 18  else if(pid>0){
 19    exit(0);//父进程,终止进程
 20  }
 21  //子进程
 22  setsid();//创建一个会话
 23  sa.sa_handler = SIG_IGN;//忽略SIGCHLD信号
 24  sigemptyset(&sa.sa_mask);
 25  sa.sa_flags = 0;
 26  if(sigaction(SIGCHLD,&sa,NULL)<0){// 注册子进程退出忽略信号
 27   return;
 28  }
 29  if((pid=fork())<0){
 30    printf("fork error!\n");
 31    return;
 32  }
 33  else if(pid!=0){
 34   exit(0);
 35  }
 36  if(chdir("/")<0){
 37    printf("child dir error\n");
 38    return;
 39  }                                                                                                                               
 40  close(0);
 41  fd0 = open("/dev/null",O_RDWR);
 42  dup2(fd0,1);
 43  dup2(fd0,2);
 44 }
 45 int main(){
 46   mydaemon();
 47   while(1)
 48    {
 49     sleep(1);
 50    }
 51}

当我们关掉一个原终端后,该进程变成了一个守护进程,在其他的终端下也可以打开,这就是守护进程的特点


当然系统已经为我们提供了将普通进程变成守护进程的方法

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main(){
  4  daemon(0,0);                                                                                                                    
  5 while(1);
  6 }
创建守护进程的时,往往要做以下两件事情
1.将进程的工作目录修改为"/"根目录,daemon的参数 nochdir为0时,即可将工作目录修改为根目录; 
 2.将标准输入,输出和错误输出重定向到/dev/null     daemon的参数 noclose为0时,输入,输出以及错误输出重定向到/dev/null 。
基于SSM框架的智能家政保洁预约系统,是一个旨在提高家政保洁服务预约效率和管理水平的平台。该系统通过集成现代信息技术,为家政公司、家政服务人员和消费者提供了一个便捷的在线预约和管理系统。 系统的主要功能包括: 1. **用户管理**:允许消费者注册、登录,并管理他们的个人资料和预约历史。 2. **家政人员管理**:家政服务人员可以注册并更新自己的个人信息、服务类别和服务时。 3. **服务预约**:消费者可以浏览不同的家政服务选项,选择合适的服务人员,并在线预约服务。 4. **订单管理**:系统支持订单的创建、跟踪和管理,包括订单的确认、完成和评价。 5. **评价系统**:消费者可以在家政服务完成后对服务进行评价,帮助提高服务质量和透明度。 6. **后台管理**:管理员可以管理用户、家政人员信息、服务类别、预约订单以及处理用户反馈。 系统采用Java语言开发,使用MySQL数据库进行数据存储,通过B/S架构实现用户与服务的在线交互。系统设计考虑了不同用户角色的需求,包括管理员、家政服务人员和普通用户,每个角色都有相应的权限和功能。此外,系统还采用了软件件化、精化体系结构、分离逻辑和数据等方法,以便于未来的系统升级和维护。 智能家政保洁预约系统通过提供一个集中的平台,不仅方便了消费者的预约和管理,也为家政服务人员提供了一个展示和推广自己服务的机会。同时,系统的后台管理功能为家政公司提供了强大的数据支持和决策辅助,有助于提高服务质量和管理效率。该系统的设计与实现,标志着家政保洁服务向现代化和网络化的转型,为管理决策和控制提供保障,是行业发展中的重要里程碑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值