`
ydbc
  • 浏览: 718296 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

Linux 的进程组、会话、守护进程

阅读更多

一、进程组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就在对应的文件中写入内容。


分享到:
评论

相关推荐

    kingking888#web.d#Linux下守护进程的创建及原理1

    进程、进程组、会话、控制终端之间的关系进程组:由一个或者多个进程组成,进程组号(GID),就是这些进程中的进程组长的 PID会话:又叫会话期,它包括了期间所有的

    linux 创建守护进程的相关知识

    创建子进程,父进程退出 这是编写守护进程的第一步。... 在子进程中创建新会话 这个步骤是创建守护进程中最重要的一步,虽然它的实现非常简单,但它的意义却非常重大。在这里使用的是系统函数setsid,在具体

    Python如何实现守护进程的方法示例

    守护进程就是Daemon程序,是一种在系统后台执行的程序,它独立于控制终端并且执行一些周期任务或触发事件,通常被命名为”d”字母结尾,如常见的httpd、syslogd、systemd和dockerd等。 代码实现 python可以很简洁地...

    python daemon守护进程实现

    假如写一段服务端程序,如果ctrl+c退出或者关闭终端,那么服务端程序就会退出,于是就想着让这个程序成为守护进程,像httpd一样,一直在后端运行,不会受终端影响。 守护进程英文为daemon,像httpd,mysqld,最后一...

    Python守护进程和脚本单例运行详解

    它必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等;它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业...

    进程线程的一些特点、信号、守护进程线程的一些锁、条件变量等知识

    主要有如何创建会话、信号的产生原因、信号处理方式、守护进程概念、线程的一些函数、互斥锁、读写锁的特点用法

    守护进程1

    在子进程中创建新的会话(脱离控制终端):这步是创建守护进程中最重要的一步,虽然实现起来很简单,但是它的意义非常重要,在这里使用的是系统函数setsid()来创建

    如何使用pm2守护你的.NET Core应用程序详解

    守护进程是一个在后台运行并且不受任何终端控制的进程,不会随着会话结束而退出。诸如 mysql、apache 等这类程序默认就提供了守护进程或者以守护进程的方式工作,我们熟悉的 “mysqld”、”httpd” 等其中的 d 就是 ...

    Linux OpenPbs 批处理作业和计算机系统资源管理软件包

    作业调度器: 作业调度器是另一个守护进程,这一进程包括site’ policy[1],这一策略控制着哪一个作业被运行,在那个节点运行,什么时候运行。因为每一个site对于什么是好的或者有效的策略都有它自己的想法,PBS...

    firejail:Linux 命名空间沙箱程序-开源

    无需编辑复杂的配置文件,无需打开套接字连接,无需后台运行的守护进程。 所有安全功能都直接在 Linux 内核中实现,并可在任何 Linux 计算机上使用。 Firejail 可以沙箱处理任何类型的进程:服务器、图形应用程序,...

    Linux FTP服务配置

    vsftp的含义就是Very Security Ftp,下面就简要的说一下它的配置和使用方法,通过本文的介绍也希望您能了解在Linux下配置一个网络服务的基本过程  1.相关配置文件  /etc/vsftpd.conf,vsftpd.ftpuser,vsftpd.user_...

    UNIX环境高级编程_第二版中文

    13.6 守护进程的惯例  13.7 客户进程-服务器进程模型  13.8 小结  习题  第14章 高级I/O  14.1 引言  14.2 非阻塞I/O  14.3 记录锁  14.4 STREAMS  14.5 I/O多路转接  14.5.1 select和pselect...

    UNIX环境高级编程

    关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在 此基础上介绍了多个应用实例,包括如何创建数据库函数库以及如何与网络打印机通信等。此外,还在附 录中给出了函数...

    UNIX环境高级编程_第2版.part1

     关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在  此基础上介绍了多个应用实例,包括如何创建数据库函数库以及如何与网络打印机通信等。此外,还在附  录中给...

    UNIX环境高级编程_第2版.part2

     关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在  此基础上介绍了多个应用实例,包括如何创建数据库函数库以及如何与网络打印机通信等。此外,还在附  录中给...

    UNIX环境高级编程(第二版中文)

    13.6 守护进程的惯例 350 13.7 客户进程-服务器进程模型 354 13.8 小结 354 习题 354 第14章 高级I/O 355 14.1 引言 355 14.2 非阻塞I/O 355 14.3 记录锁 357 14.4 STREAMS 370 14.5 I/O多路转接...

    unix环境编程电子书

    进程关系 213 9.1 引言 213 9.2 终端登录 213 9.3 网络登录 216 9.4 进程组 218 9.5 会话 219 9.6 控制终端 220 9.7 tcgetpgrp、tcsetpgrp和tcgetsid函数 221 9.8 作业控制 222 9.9 shell执行程序...

    ARM_Linux启动分析.pdf

    init进程是系统所有进程的起点,内核在完成核内引导以后,即在本线程(进程)空 间内加载init程序,它的进程号是1。 init程序需要读取/etc/inittab文件作为其行为指针,inittab是以行为单位的描述性(非执行性)...

Global site tag (gtag.js) - Google Analytics