现在的位置: 首页 > 综合 > 正文

linux进程组、会话和守护进程

2014年09月02日 ⁄ 综合 ⁄ 共 3376字 ⁄ 字号 评论关闭
文章目录

一、进程组和会话的关系图

二、进程组

显示进程组

函数介绍


#include <unistd.h>
pid_t getpgrp(void);
功能:返回进程组ID
 
pid_t getpgid(pid_t pid);
功能:返回pid的进程组ID

显示子进程和父进程的进程组ID

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main() 
{
    pid_t pid;
 
    if ((pid=fork())<0) 
    {   
        printf("fork error.\n");
    }
    else if (pid==0) //子进程
    {
        printf("The child process PID is %d.\n",getpid());
        printf("The Group ID is %d.\n",getpgrp());
        printf("The Group ID is %d.\n",getpgid(0));
        printf("The Group ID is %d.\n",getpgid(getpid()));
        exit(0);
    }
 
    // 父进程   
    sleep(3);
    printf("The parent process PID is %d.\n",getpid());
    printf("The Group ID is %d.\n",getpgrp());
 
    return 0;
}
 
结果:
[root@f8s setsid_test]# ./show_groupid 
The child process PID is 2929.
The Group ID is 2928.
The Group ID is 2928.
The Group ID is 2928.
The parent process PID is 2928.
The Group ID is 2928.
[root@f8s setsid_test]#

改变进程组

函数介绍

#include <unistd.h>
int setpgid(pid_t pid, pid_t pgid);
功能:加入现有的进程组或创建一个新进程组
返回值:成功返回0,出错返回-1

进程为自己或子进程设置进程组ID

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main()
{
    pid_t pid;
 
    if ((pid=fork())<0) 
    {
        printf("fork error.\n");
        exit(1);
    }
    else if (pid==0) // 子进程
    {
        printf("The child process PID is %d.\n",getpid());   // 子进程ID
        printf("The Group ID of child is %d.\n",getpgid(0)); // 返回组id
        sleep(5);
        printf("The Group ID of child is changed to %d.\n",getpgid(0)); // 显示子进程的组ID
        exit(0);
    }
 
    sleep(1);
    setpgid(pid,pid); // 改变子进程的组id为子进程本身
 
    sleep(5);
    printf("The parent process PID is %d.\n",getpid());
    printf("The parent of parent process PID is %d.\n",getppid());
    printf("The Group ID of parent is %d.\n",getpgid(0));
    setpgid(getpid(),getppid()); // 改变父进程的组id为父进程的父进程
    printf("The Group ID of parent is changed to %d.\n",getpgid(0));
 
    return 0;
}
 
结果:
[root@f8s setsid_test]# gcc change_groupid.c -o change_groupid
[root@f8s setsid_test]# ./change_groupid 
The child process PID is 2949.
The Group ID of child is 2948.
The Group ID of child is changed to 2949.
The parent process PID is 2948.
The parent of parent process PID is 2870.
The Group ID of parent is 2948.
The Group ID of parent is changed to 2870.
[root@f8s setsid_test]#

三、会话

概念

会话是一个或多个进程组的集合

函数介绍

#include <unistd.h>
pid_t setsid(void):
功能:建立新会话(调用进程是组长进程,则出错返回)
返回值: 成功返回进程组ID, 出错返回-1
 
pid_t getsid(pid_t pid)
功能:获取会话ID
返回值:成功返回会话首进程的进程组ID,出错返回-1

子进程调用setsid后,成为新会话的首进程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main() 
{
    pid_t pid;
 
    if ((pid=fork())<0) 
    {
        printf("fork error.\n");
        exit(1);
    }
    else if (pid==0) // 子进程
    {
        printf("The child process PID is %d.\n",getpid());
        printf("The Group ID of child is %d.\n",getpgid(0));
        printf("The Session ID of child is %d.\n",getsid(0));
        sleep(10);
        setsid(); // 子进程非组长进程,故其成为新会话首进程,且成为组长进程。该进程组id即为会话进程
        printf("Changed:\n");
        printf("The child process PID is %d.\n",getpid());
        printf("The Group ID of child is %d.\n",getpgid(0));
        printf("The Session ID of child is %d.\n",getsid(0));
        sleep(20);
        exit(0);
    }
 
    return 0;
}
 
结果:
[root@f8s setsid_test]# ./setsid_test 
The child process PID is 2969.
The Group ID of child is 2968.
The Session ID of child is 2870.
[root@f8s setsid_test]# Changed:
The child process PID is 2969.
The Group ID of child is 2969.
The Session ID of child is 2969.

四、守护进程

守护进程创建步骤

  1. 创建子进程,父进程退出(fork)
  2. 子进程中创建新会话(setsid)
  3. 改变当前目录为跟目录(chdir)
  4. 重设文件权限掩码(umask)
  5. 关闭文件描述符(getdtablesize)

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
 
int main() 
{
    pid_t pid;
    int i,fd;
 
    if ((pid=fork())<0)  // 出错
    {
        printf("fork error.\n");
        exit(1);
    }else if (pid>0)  // fork且退出父进程
        exit(0);
 
    setsid();    // 在子进程中创建新会话。
    chdir("/");  // 设置工作目录为根
    umask(0);    // 设置权限掩码
    for(i=0; i < getdtablesize(); i++)  //getdtablesize返回子进程文件描述符表的项数
        close(i);                	// 关闭这些不将用到的文件描述符
 
    while(1) 
    {
        sleep(10);
        printf("Never print!\n");    // 由于文件描述符关闭,不会输出到终端
    }
 
    return 0;
}
 
结果:
[root@f8s setsid_test]# ps -axj | grep daemon
    1  3022  3022  3022 ?           -1 Ss       0   0:00 ./daemon
<source>

抱歉!评论已关闭.