zoukankan      html  css  js  c++  java
  • Linux--进程组、会话、守护进程(转)

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

    进程组

      一个或多个进程的集合
      进程组ID: 正整数
      两个函数
      getpgid(0)=getpgrp()

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

    复制代码
     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. ",getpid());
    12 printf("The Group ID is %d. ",getpgrp());
    13 printf("The Group ID is %d. ",getpgid(0));
    14 printf("The Group ID is %d. ",getpgid(getpid()));
    15 exit(0);
    16 }
    17
    18 sleep(3);
    19 printf("The parent process PID is %d. ",getpid());
    20 printf("The Group ID is %d. ",getpgrp());
    21
    22 return 0;
    23 }
    复制代码

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

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

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

    复制代码
     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. ",getpid());
    13 printf("The Group ID of child is %d. ",getpgid(0)); // 返回组id
    14 sleep(5);
    15 printf("The Group ID of child is changed to %d. ",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. ",getpid());
    24 printf("The parent of parent process PID is %d. ",getppid());
    25 printf("The Group ID of parent is %d. ",getpgid(0));
    26 setpgid(getpid(),getppid()); // 改变父进程的组id为父进程的父进程
    27 printf("The Group ID of parent is changed to %d. ",getpgid(0));
    28
    29 return 0;
    30 }
    复制代码

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

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

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

    复制代码
     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. ",getpid());
    13 printf("The Group ID of child is %d. ",getpgid(0));
    14 printf("The Session ID of child is %d. ",getsid(0));
    15 sleep(10);
    16 setsid(); // 子进程非组长进程,故其成为新会话首进程,且成为组长进程。该进程组id即为会话进程
    17 printf("Changed: ");
    18 printf("The child process PID is %d. ",getpid());
    19 printf("The Group ID of child is %d. ",getpgid(0));
    20 printf("The Session ID of child is %d. ",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 #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. ";
    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! ");
    30 exit(1);
    31 }
    32 // 将buf写到fd中
    33 write(fd,buf,strlen(buf)+1);
    34 close(fd);
    35 sleep(10);
    36 printf("Never output! ");
    37 }
    38
    39 return 0;
    40 }
    复制代码

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

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

  • 相关阅读:
    input上传限定文件类型
    扫描二维码自动识别手机系统(Android/IOS)
    css/html/Javascript
    移动端容易碰到的点击穿透的坑
    洛谷P3387 【模板】缩点
    洛谷P1137 旅行计划
    洛谷P2324 [SCOI2005]骑士精神
    洛谷P2571 [SCOI2010]传送带
    BZOJ4300: 绝世好题
    [洛谷P1966] 火柴排队
  • 原文地址:https://www.cnblogs.com/fightformylife/p/4140032.html
Copyright © 2011-2022 走看看