http://www.cnblogs.com/forstudy/archive/2012/04/03/2427683.html

进程组

  一个或多个进程的集合
  进程组ID: 正整数
  两个函数

  getpgid(0)=getpgrp()

eg:显示子进程与父进程的进程组id

  1. 1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <unistd.h>
    4
    5 int main() {
    6 pid_t pid;
    7
    8 if ((pid=fork())<0) {
    9 printf("fork error!");
    10 }else if (pid==0) {
    11 printf("The child process PID is %d.\n",getpid());
    12 printf("The Group ID is %d.\n",getpgrp());
    13 printf("The Group ID is %d.\n",getpgid(0));
    14 printf("The Group ID is %d.\n",getpgid(getpid()));
    15 exit(0);
    16 }
    17
    18 sleep(3);
    19 printf("The parent process PID is %d.\n",getpid());
    20 printf("The Group ID is %d.\n",getpgrp());
    21
    22 return 0;
    23 }

进程组id = 父进程id,即父进程为组长进程

组长进程
  组长进程标识: 其进程组ID==其进程ID
  组长进程可以创建一个进程组,创建该进程组中的进程,然后终止
  只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关
  进程组生存期: 进程组创建到最后一个进程离开(终止或转移到另一个进程组)
 
一个进程可以为自己或子进程设置进程组ID
  setpgid()加入一个现有的进程组或创建一个新进程组

eg:父进程改变自身和子进程的组id

  1. 1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <unistd.h>
    4
    5 int main() {
    6 pid_t pid;
    7
    8 if ((pid=fork())<0) {
    9 printf("fork error!");
    10 exit(1);
    11 }else if (pid==0) {
    12 printf("The child process PID is %d.\n",getpid());
    13 printf("The Group ID of child is %d.\n",getpgid(0)); // 返回组id
    14 sleep(5);
    15 printf("The Group ID of child is changed to %d.\n",getpgid(0));
    16 exit(0);
    17 }
    18
    19 sleep(1);
    20 setpgid(pid,pid); // 改变子进程的组id为子进程本身
    21
    22 sleep(5);
    23 printf("The parent process PID is %d.\n",getpid());
    24 printf("The parent of parent process PID is %d.\n",getppid());
    25 printf("The Group ID of parent is %d.\n",getpgid(0));
    26 setpgid(getpid(),getppid()); // 改变父进程的组id为父进程的父进程
    27 printf("The Group ID of parent is changed to %d.\n",getpgid(0));
    28
    29 return 0;
    30 }

会话: 一个或多个进程组的集合
  开始于用户登录
  终止与用户退出
  此期间所有进程都属于这个会话期

建立新会话:setsid()函数
  该调用进程是组长进程,则出错返回
    先调用fork, 父进程终止,子进程调用
  该调用进程不是组长进程,则创建一个新会话
    •该进程变成新会话首进程(session header)
    •该进程成为一个新进程组的组长进程。
    •该进程没有控制终端,如果之前有,则会被中断
组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程...

会话ID:会话首进程的进程组ID
获取会话ID: getsid()函数

  1. 1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <unistd.h>
    4
    5 int main() {
    6 pid_t pid;
    7
    8 if ((pid=fork())<0) {
    9 printf("fork error!");
    10 exit(1);
    11 }else if (pid==0) {
    12 printf("The child process PID is %d.\n",getpid());
    13 printf("The Group ID of child is %d.\n",getpgid(0));
    14 printf("The Session ID of child is %d.\n",getsid(0));
    15 sleep(10);
    16 setsid(); // 子进程非组长进程,故其成为新会话首进程,且成为组长进程。该进程组id即为会话进程
    17 printf("Changed:\n");
    18 printf("The child process PID is %d.\n",getpid());
    19 printf("The Group ID of child is %d.\n",getpgid(0));
    20 printf("The Session ID of child is %d.\n",getsid(0));
    21 sleep(20);
    22 exit(0);
    23 }
    24
    25 return 0;
    26 }

在子进程中调用setsid()后,子进程成为新会话首进程,且成为一个组长进程,其进程组id等于会话id

守护进程
  Linux大多数服务都是通过守护进程实现的,完成许多系统任务
  0: 调度进程,称为交换进程(swapper),内核一部分,系统进程
  1: init进程, 内核调用,负责内核启动后启动Linux系统
  没有终端限制
  让某个进程不因为用户、终端或者其他的变化而受到影响,那么就必须把这个进程变成一个守护进程
 
守护进程编程步骤
  1. 创建子进程,父进程退出
    •所有工作在子进程中进行
    •形式上脱离了控制终端
  2. 在子进程中创建新会话
    •setsid()函数
    •使子进程完全独立出来,脱离控制
  3. 改变当前目录为根目录
    •chdir()函数
    •防止占用可卸载的文件系统
    •也可以换成其它路径
  4. 重设文件权限掩码
    •umask()函数
    •防止继承的文件创建屏蔽字拒绝某些权限
    •增加守护进程灵活性
  5. 关闭文件描述符
    •继承的打开文件不会用到,浪费系统资源,无法卸载
    •getdtablesize()
    •返回所在进程的文件描述符表的项数,即该进程打开的文件数目

  1. 1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <string.h>
    4 #include <unistd.h>
    5 #include <sys/wait.h>
    6 #include <sys/types.h>
    7 #include <fcntl.h>
    8
    9 int main() {
    10 pid_t pid;
    11 int i,fd;
    12 char *buf="This is a daemon program.\n";
    13
    14 if ((pid=fork())<0) {
    15 printf("fork error!");
    16 exit(1);
    17 }else if (pid>0) // fork且退出父进程
    18 exit(0);
    19
    20 setsid(); // 在子进程中创建新会话。
    21 chdir("/"); // 设置工作目录为根
    22 umask(0); // 设置权限掩码
    23 for(i=0;i<getdtablesize();i++) //getdtablesize返回子进程文件描述符表的项数
    24 close(i); // 关闭这些不将用到的文件描述符
    25
    26 while(1) {// 死循环表征它将一直运行
    27 // 以读写方式打开"/tmp/daemon.log",返回的文件描述符赋给fd
    28 if ((fd=open("/tmp/daemon.log",O_CREAT|O_WRONLY|O_APPEND,0600))<0) {
    29 printf("Open file error!\n");
    30 exit(1);
    31 }
    32 // 将buf写到fd中
    33 write(fd,buf,strlen(buf)+1);
    34 close(fd);
    35 sleep(10);
    36 printf("Never output!\n");
    37 }
    38
    39 return 0;
    40 }

因为stdout被关掉了,所以“Never ouput!”不会输出。

查看/tmp/daemon.log,说明该程序一直在运行

Linux--进程组、会话、守护进程(转)的更多相关文章

  1. linux 进程通信之 守护进程

    守护进程(Daemon) Daemon(精灵)进程,是linux中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的时间.一般采用以d结尾的名字.从下面的进程信息可以看出, ...

  2. linux系统编程--守护进程,会话,进程组,终端

    终端: 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal), 进程中,控制终端是保存在PCB中的信息,而f ...

  3. linux下的守护进程及会话、进程组

    守护进程.会话.进程组网上有许多不错的资料.我也是网上搜罗了一堆,加上自己的理解.不敢说原创,只是写在这怕自己忘记罢了.才疏学浅,难免有错误,欢迎大家指正.下面这篇写很不错,大家可以去看看:http: ...

  4. Linux编程之《守护进程》

    Intro ----- 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常 ...

  5. Linux 下Qt实现守护进程实例(转)

     原文地址:Linux守护进程的编程方法(含实例) 作者:lingdxuyan 参考文献 Linux信号列表(zz) Linux 守护进程的编程方法 linux上编写守护进程的例程 Linux下后台守 ...

  6. Linux系统编程之--守护进程的创建和详解【转】

    本文转载自:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终 ...

  7. Linux下一个简单守护进程的实现 (Daemon)

    在Linux/UNIX系统引导的时候会开启很多服务,这些服务称为守护进程(也叫Daemon进程).守护进程是脱离于控制终端并且在后台周期性地执行某种任务或等待处理某些事件的进程,脱离终端是为了避免进程 ...

  8. linux系统编程:守护进程详解及创建,daemon()使用

    一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...

  9. 一只简单的网络爬虫(基于linux C/C++)————守护进程

    守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系统引导装入时启动, ...

  10. Linux 进程(二):进程关系及其守护进程

    进程关系 进程组 进程组是一个或多个进程的集合.通常,它们是在同一作业中结合起来的,同一进程组中的各进程接收来自同一终端的各种信号,每个进程组有一个唯一的进程组ID.每个进程组有一个组长进程,该组长进 ...

随机推荐

  1. TFS2010升级至TFS2013完全指南(更换服务器)

    一.背景:         公司已使用tfs2010很长时间,目前随着公司的发展,项目越来越少,而产品越来越多,采用的开发模式,也逐渐从瀑布式.迭代式转向敏捷开发.为了更好的支持产品研发,决定将tfs ...

  2. Javaweb学习笔记5—Cookie&Session

    今天来讲javaweb的第五阶段学习. Cookie和Session同样是web开发常用到的地方. 老规矩,首先先用一张思维导图来展现今天的博客内容. ps:我的思维是用的xMind画的,如果你对我的 ...

  3. PMP项目管理学习笔记(4)——项目整合管理

    六个整合管理过程. 1.制定项目章程 一个新项目要完成的第一件事,就是项目章程的制定.这是授权你开展工作的文档.不过并不总是需要你介入,通常情况下会由赞助人交给你.如果没有项目章程,你就没有权利告诉你 ...

  4. 【HEVC帧间预测论文】P1.4 Motion Vectors Merging: Low Complexity Prediction Unit Decision

    Motion Vectors Merging: Low Complexity Prediction Unit Decision Heuristic for the inter-Prediction o ...

  5. toast插件的简单封装(样式适用pc后台管理系统的场景)

    直接分三个步骤吧: 1.手写一个toast.vue组件 <template> <transition name="toast-fade"> <div ...

  6. bitcoin 源码解析 - 交易 Transaction

    bitcoin 源码解析 - 交易 Transaction(三) - Script 之前的章节已经比较粗略的解释了在Transaction体系当中的整体运作原理.接下来的章节会对这个体系进行分解,比较 ...

  7. HTML习题附答案

    第一章 1.HTML指的是(   A   ). A超文本标记语言(Hyper Text Markup Language) B家庭工具标记语言(Home Tool Markup Language) C超 ...

  8. image的resizeMode属性

    Image组件必须在样式中声明图片的宽和高.如果没有声明,则图片将不会被呈现在界面上.    我们一般将Image定义的宽和高乘以当前运行环境的像素密度称为Image的实际宽高. 当Image的实际宽 ...

  9. CF161D Distance in Tree 点分治

    题目: 输入点数为N一棵树,求树上长度恰好为K的路径个数 分析: 题目的数据范围不是很紧,点分治也可以过,树形dp也可以过.这里采用点分治做法. 我们只需要单开一个类似于桶的数组,跑点分治套路,统计即 ...

  10. AHOI2014/JSOI2014 奇怪的计算器

    题目描述 题解: 考虑到经过一系列变化后小数不可能比大数大,我们可以用线段树维护区间修改. 重点是,每个节点都可以通过$a[i]=a[i]*t1+a0[i]*t2+t3$这个函数来表示,我们就可以把三 ...