Linux并发程序设计(3):守护进程
创始人
2024-09-25 18:21:57
0

目录

前言

一、介绍

1.1 概念

1.2 特点

1.3 举例

二、系统编程

2.1 setsid函数

2.2 getpid函数

2.3 getsid函数

2.4 getpgid函数

2.5 chdir函数

三、代码例程

3.1 使子进程在后台运行

3.2 使子进程脱离原终端

3.3 更换目录,并设定权限(非必须)

3.4 关闭打开的文件描述符

3.5 完整代码 

3.6 代码实验 

总结


前言

本文介绍Linux系统中的三大进程类型之一——守护进程。

一、介绍

1.1 概念

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

其他相关概念:

  • 进程组(Process Group): 进程集合,每个进程组有一个组长(Leader),其进程 ID 就是该进程组 ID。
  • 会话(Session): 进程组集合,每个会话有一个组长,其进程 ID 就是该会话组 ID。
  • 控制终端(Controlling Terminal):每个会话可以有一个单独的控制终端,与控制终端连接的 Leader 就是控制进程(Controlling Process)。

图1 进程、进程组和会话的示意图

1.2 特点

始终在后台运行,独立于任何终端,周期性的执行某种任务或等待处理特定事件。

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

1.3 举例

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

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

nohup  xxxx  &

二、系统编程

2.1 setsid函数

pid_t setsid(void);

功能:子进程创建新会话 。

成功:返回调用进程的会话ID;失败:-1,设置errno。
调用了setsid函数的进程,既是新的会长,也是新的组长

2.2 getpid函数

pid_t getpid(void); 

功能:获取当前进程的pid。

2.3 getsid函数

pid_t getsid(pid_t pid)

功能:返回调用进程的会话ID

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

如若pid是0,getsid返回调用进程的会话ID;

如若pid并不属于调用者所在的会话,那么调用进程就不能得到该会话ID。

2.4 getpgid函数

pid_t getpgid(pid_t pid);

功能:获取指定进程(通过其进程标识符 pid)所属的进程组id

2.5 chdir函数

int chdir(const char * path); 

功能:将当前的工作目录改变成以参数路径所指的目录。

2.6 umask函数

mode_t umask(mode_t mask);

功能:umask()会将系统umask值设成(mode&~mask)的权限值。

例如:

在建立文件时指定文件权限为0666, 通常umask 值默认为022, 则该文件的真正权限则为0666&~022=0644, 也就是rw-r--r--返回值此调用不会有错误值返回. 返回值为原先系统的umask 值。

三、代码例程

3.1 使子进程在后台运行

  pid_t pid;   pid = fork();   if(pid<0){     perror("fork");     return 0;   }   else if(pid>0){     exit(0);   }   printf("I am a deamon\n");   printf("sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));

3.2 使子进程脱离原终端

if(setsid()<0){     perror("setsid");     exit(0); }   printf("after sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));

3.3 更换目录,并设定权限(非必须)

  chdir("/");    if(umask(0)<0){     perror("unmask");     exit(0);   }

3.4 关闭打开的文件描述符

已脱离终端,stdin / stdout / stderr无法再使用,故关闭当前的文件描述符。

  close(0);   close(1);   close(2);

3.5 完整代码 

#include  #include  #include  #include  int main(){   pid_t pid;   pid = fork();   if(pid<0){     perror("fork");     return 0;   }   else if(pid>0){     exit(0);   }   printf("I am a deamon\n");   printf("sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));    if(setsid()<0){     perror("setsid");     exit(0);   }      printf("after sid=%d,pid=%d,pgid=%d\n",getsid(getpid()),getpid(),getpgid(getpid()));   chdir("/");    if(umask(0)<0){     perror("unmask");     exit(0);   }      close(0);   close(1);   close(2);   printf("after close \n");      sleep(100);    return 0; } 

3.6 代码实验 

四、总结

从代码实验可以看出,我们以及成功的创建了守护进程,并且让它“当家做主人”,成为了会话的组长,同时我们也可以看到,因为关闭了打开的文件描述符,最后的“after close \n”并没有被成功打印出来。

相关内容

热门资讯

透视讲解!wepoker辅助软... 透视讲解!wepoker辅助软件价格(透视)wepoker能不能透视(切实真的有挂)wepoker辅...
透视计算!德州透视脚本(透视)... 透视计算!德州透视脚本(透视)黑科技教程(2020已更新)(哔哩哔哩)1、用户打开应用后不用登录就可...
透视苹果版!wepoker透视... 透视苹果版!wepoker透视脚本(透视)辅助是真的假的(原来是有挂)1、点击下载安装,wepoke...
透视插件!wepokerplu... 透视插件!wepokerplus脚本(透视)wepoker是不是有人用挂(都是有挂)1、wepoke...
透视挂!pokermaster... 透视挂!pokermaster脚本(透视)必胜教程(2022已更新)(哔哩哔哩);1、pokerma...
透视ai代打!wepoker透... 透视ai代打!wepoker透视脚本免费使用视频(透视)辅助透视软件(一直真的是有挂)1、首先打开w...
透视脚本!WePoKer辅助器... 透视脚本!WePoKer辅助器(透视)wepoker脚本下载(竟然是有挂)1、下载好wepoker脚...
透视好友!wepoker有没有... 透视好友!wepoker有没有机器人(透视)有机器人(都是有挂)1、让任何用户在无需wepoker有...
透视存在!哈糖大菠萝有挂吗(透... 透视存在!哈糖大菠萝有挂吗(透视)可靠技巧(2023已更新)(哔哩哔哩);哈糖大菠萝有挂吗辅助器中分...
透视ai!wepokerplu... 透视ai!wepokerplus到底是挂了吗(透视)wepoker私人局透视教程(总是存在有挂);1...