一、进程组ID

每个进程都属于一个进程组。每个进程组有一个领头进程。进程组是一个或多个进程的集合,通常它们与一组作业相关联,可以接受来自同一终端的各种信号。每个进程组都有唯一的进程组ID(整数,也可以存放在pid_t类型中)。进程组由进程组ID来唯一标识。除了进程号外(PID)之外,进程组ID也是一个进程的必备属性之一。

getpgrp: 获得进程组 id, 即领头进程的 pid
#include <unistd.h>
pid_t getpgrp(void);
//返回值;调用进程的进程组ID

#include<unistd.h>
pid_t getpgid(pid_t pid);
//若成功返回进程组id,失败则返回-1.

每个进程组都有一个组长进程,组长进程的进程号等于进程组ID。组长进程可以创建一个进程组、创建该组中的进程。只要某个进程组中有一个进程存在,则该进程组就存在,与组长进程是否终止无关。从进程组创建开始到其中最后一个进程离开为止的时间区间成为进程组的生存期。进程组中最后一个进程可以终止或者转移到另一个进程组中。
显示子进程和父进程的组id
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main() {
pid_t pid; if ((pid=fork())<0) {
printf("fork error!");
}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;
}

程序执行的结果:

二、会话
会话是一个或多个进程组的集合。例如:


#include<unistd.h>
pid_t setsid(void);
如果调用此函数的进程不是一个进程组的组长,则此函数就会创建一个新的会话,结果发生三件事:
1、该进程变成新会话的首进程。此时,该进程是新会话中唯一的进程。
2、该进程成为一个进程组的组长进程。新的进程组ID就是调用进程的ID。
3、该进程没有控制终端。如果在调用setsid之前该进程有一个控制终端,那么这种联系也会断掉。
如果该进程已经是一个进程组的组长,则此函数返回错误。为了保证不会发生这种事情,通常先调用fork,然后使其父进程终止,而子进程则继续。因为子进程继承了父进程的组ID,而其ID是新分配,两者不可能相等,所以就保证了子进程不会是一个进程组长。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main() {
pid_t pid; if ((pid=fork())<0) {
printf("fork error!");
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);
}

程序执行的结果:


三、守护进程
在linux或者unix系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程。为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统。 守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。
守护进程编程步骤
1. 创建子进程,父进程退出
•所有工作在子进程中进行
•形式上脱离了控制终端
2. 在子进程中创建新会话
•setsid()函数
•使子进程完全独立出来,脱离控制
3. 改变当前目录为根目录
•chdir()函数
•防止占用可卸载的文件系统
•也可以换成其它路径
4. 重设文件权限掩码
•umask()函数
•防止继承的文件创建屏蔽字拒绝某些权限
•增加守护进程灵活性
5. 关闭文件描述符
•继承的打开文件不会用到,浪费系统资源,无法卸载
•getdtablesize()
•返回所在进程的文件描述符表的项数,即该进程打开的文件数目



该实例首先创建了一个守护进程,然后让该守护进程每个10s在/tmp/dameon.log中写入一句话。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h> #define MAXFILE 65535
int main()
{
pid_t pc;
int i,fd,len;
char *buf="This is a Dameon\n";
len =strlen(buf);
pc=fork();
if(pc<0){
printf("error fork\n");
exit(1);
}else if(pc>0)
exit(0);
setsid();
chdir("/");
umask(0);
for(i=0;i<MAXFILE;i++)
close(i);
while(1){
if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND,0600))<0){
perror("open");
exit(1);
}
write(fd, buf, len+1);
close(fd);
sleep(10);
}
}

我们可以看到程序每个10s就在对应的文件中写入内容。

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

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

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

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

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

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

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

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

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

  5. ASP.NET Core Linux下为 dotnet 创建守护进程(必备知识)

    前言 在上篇文章中介绍了如何在 Docker 容器中部署我们的 asp.net core 应用程序,本篇主要是怎么样为我们在 Linux 或者 macOs 中部署的 dotnet 程序创建一个守护进程 ...

  6. Linux中的两种守护进程stand alone和xinetd

    Linux中的两种守护进程stand alone和xinetd --http://www.cnblogs.com/itech/archive/2010/12/27/1914846.html#top 一 ...

  7. ASP.ENT Core Linux 下 为 donet创建守护进程(转载)

    原文地址:http://www.cnblogs.com/savorboard/p/dotnetcore-supervisor.html 前言 在上篇文章中介绍了如何在 Docker 容器中部署我们的 ...

  8. Linux网络编程学习(四) -----守护进程的建立(第三章)

    本文介绍一个例程daemon_init() #include <sys/types.h> #include <signal.h> #include <unistd.h&g ...

  9. Linux进程托管与守护进程设置

    引言 在上一篇<Linux启动之旅>中,我们了解了Linux启动过程,在该过程的最后一步,init进程拉起/etc/init.d/rcN.d/目录下指定的守护进程(daemon).假若自定 ...

  10. Windows 和 Linux 上Redis的安装守护进程配置

    # Windows 和 Linux 上Redis的安装守护进程配置 Redis 简介 ​ Redis是目前最常用的非关系型数据库(NOSql)之一,常以Key-Value的形式存储.Redis读写速度 ...

随机推荐

  1. git for windows+TortoiseGit客户端的使用

        一.安装Git客户端 全部安装均采用默认! 1. 安装支撑软件 : https://code.google.com/p/msysgit/downloads/list?q=full+instal ...

  2. objcopy

    objcopy objcopy [options] infile [outfile] Copy the contents of the input object file to another fil ...

  3. uva1637Double Patience

    状态压缩,记忆化搜索. 用一个5进制数来表示每堆排到了哪一个位置.和2进制是一样的,不过不能用位运算. #include<cstdio> #include<algorithm> ...

  4. WebService只能在本地使用,无法通过网络访问的解决办法

    问题描述:WebService只能在本地使用,无法通过网络访问. 解决方案:在web.config的<system.web></system.web>中间加入如下配置节内容: ...

  5. ASP.NET MVC 学习4、Controller中添加SearchIndex页面,实现简单的查询功能

    参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-method ...

  6. Java知识点:instanceof关键字

    介绍 格式:a instanceof B,其中a是一个variable(设a所指向的对象的类型命名为A,即A是一个type. 功能:判断A是否 is-a B. 当a=null时,始终返回false. ...

  7. eclipse export Android jar with jni

    /*********************************************************************** * eclipse export Android ja ...

  8. FZU 1591 Coral的烦恼

    Problem Description 程序设计课的老师给Coral布置了一道题:用T(n)表示所有能整除n的正整数之和,对于给定的数字n,记S(n)=T(1)+T(2)+…+ T(n).你的任务就是 ...

  9. cmd远程连接数据库

    在本地配置tnsname 打开C:\oracle\ora92\network\ADMIN\tnsnames.ora 加入如下参数. ora = (DESCRIPTION = (ADDRESS_LIST ...

  10. Oracle EM 不能访问

    zwt2001267 原文 Oracle EM 不能访问 1. cmd控制启动EM: C:\Users\Administrator>emctl start dbconsoleEnvironmen ...