Linux系统编程(进程组)

简介: Linux系统编程(进程组)

前言

本篇文章我们开始学习Linux中的进程组,进程组这个概念可能很多小伙伴都没有接触过,那么这篇文章将会教大家什么是进程组。

一、进程组概念

在操作系统中,进程组(Process Group)是一组相关联的进程的集合。每个进程组都有一个唯一的进程组ID(PGID)。

进程组的主要目的是为了实现作业控制(Job Control),即对一组相关的进程进行协调和管理。有些操作系统使用进程组来组织与终端会话(Terminal Session)相关的进程,以实现对终端的控制和管理。

以下是进程组的几个重要特点:

1.进程组中的进程共享同一个进程组ID(PGID)。

2.进程组中的每个进程都有一个唯一的进程ID(PID)。

3.进程组中的进程可以通过进程组ID或进程ID来标识和引用。

4.进程组可以有一个领导进程(Group Leader),它是进程组中的一个成员,但其PID与PGID相同。

5.进程组可以具有一个控制终端(Controlling Terminal),用于与终端会话相关联。

6.进程组可以用来实现作业控制,例如启动、停止、恢复、终止一组相关的进程。

通过进程组,操作系统可以对一组相关的进程进行集中管理和控制。例如,在一个终端会话中,用户可以使用作业控制命令如fg(将一个后台作业移到前台运行)、bg(将一个前台作业移至后台运行)和kill(终止一个作业)来控制和管理进程组中的进程。

进程组是多进程编程和系统管理中的重要概念,对于实现进程间通信、作业控制和并发编程等都具有重要意义。

二、进程组编程实验

首先先介绍三个相关的函数:

当一个进程组中的进程需要访问或修改进程组的相关信息时,可以使用以下三个系统调用:getpgrp,getpgid和setpgid。我将逐个解释它们的作用和用法。

getpgrp():

getpgrp()是一个系统调用,用于获取调用进程所属的进程组ID(PGID),即获取当前进程的进程组ID。其原型为:

pid_t getpgrp(void);

声明中的pid_t是一个整数类型,表示进程组ID。调用getpgrp()会返回当前进程所属的进程组ID。

getpgid():

getpgid()是一个系统调用,用于获取指定进程的进程组ID。其原型为:

pid_t getpgid(pid_t pid);

参数pid是指定进程的进程ID。调用getpgid(pid)会返回进程ID为pid的进程所属的进程组ID。

setpgid():

setpgid()是一个系统调用,用于设置指定进程的进程组ID。其原型为:

int setpgid(pid_t pid, pid_t pgid);

参数pid是指定进程的进程ID,参数pgid是要设置的进程组ID。调用setpgid(pid, pgid)会将进程ID为pid的进程的进程组ID设置为pgid。

但需要注意的是,在使用setpgid()进行设置时,有以下几种情况:

如果将pgid设置为0,表示将指定进程的进程组ID设置为其本身的进程ID。

如果将pgid设置为与指定进程的进程ID相同,表示将指定进程设置为新的进程组领导者(Group Leader)。

如果指定的pid与pgid参数相同,表示将当前进程设置为新的进程组领导者。

这些函数在多进程编程和作业控制中非常有用。例如,可以使用getpgrp()来获取当前进程所属的进程组ID,getpgid()可以用于获取指定进程的进程组ID,而setpgid()则可以用于更改进程的进程组ID。这些函数能够帮助进程组协同工作和实现作业控制的功能。

示例代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
    pid_t pid = fork();
    if(pid == 0)
    {
        printf("child pid : %d gpid : %d\n", getpid(), getpgrp());
    }
    else
    {
        printf("parent pid : %d gpid : %d\n", getpid(), getpgrp());
    }
    return 0;
}

通过运行结果可以发现子进程和父进程属于同一个进程组。

三、进程组组长

1.进程组组长概念

进程组的组长是由操作系统内核根据一定规则设置的,并且通常是创建进程组的第一个进程。该进程组的组长进程ID(PID)与进程组ID(PGID)相同。

进程组组长的主要作用是:

1.进程组管理:

组长负责管理组内的其他进程。它可以使用setpgid()系统调用来创建新的进程组,并将其他进程加入到自己的进程组中。

2.作业控制:

Unix操作系统下,作业控制(Job Control)是一种管理和控制前台和后台进程运行的机制。进程组组长在作业控制中起着重要的角色,它可以向操作系统发出信号以控制整个进程组的状态,如暂停(SIGSTOP)、继续(SIGCONT)或终止(SIGTERM)等。

3.进程间通信:

进程组组长还可以作为进程间通信的机制之一。组长可以通过进程组ID将消息发送给同一进程组中的其他成员进程。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
    pid_t pid = 0;
    int i = 0;
    for(i = 0; i < 5; i++)
    {        
        if((pid = fork()) > 0)
        {
            printf("parent pid :%d gpid : %d \n", getpid(), getpgrp());
        }
        else if(pid == 0)
        {
            printf("child pid :%d gpid : %d \n", getpid(), getpgrp());
            sleep(50);
            break;           
        }
        else
        {
            printf("fork err\n");
        }
    }
    sleep(120);
    return 0;
}

运行结果:

创建出的子进程和父进程属于同一个进程组,并且父进程作为进程组长。

使用下面命令可以一次性的将进程组中的进程都杀死。

进程组组长被终止后,其他的进程还是存在的,进程组组长只是用于创建新的进程。

2.改变进程的进程组依附性

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
    pid_t pid = 0;
    int i = 0;
    if((pid = fork()) > 0)
    {
        setpgid(pid, pid);
        printf("parent pid : %d pgid : %d\n", getpid(), getpgrp());
    }
    else if(pid == 0)
    {
        setpgid(pid, pid);
        printf("child pid : %d pgid : %d\n", getpid(), getpgrp());
    }
    return 0;
}

运行结果:

这里可以看到子进程的进程组已经被修改了,并且成为了进程组长。

那么为什么需要调用两次setpgid函数呢,因为创建完子进程后,无法确认是子进程先运行还是父进程先运行,所以在这里调用两次setpgid函数确保生效。

总结

本篇文章主要给大家讲解了进程组的概念和学习了如何修改进程组的依附性。


相关文章
|
29天前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
66 1
|
18天前
|
存储 缓存 监控
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
151 78
|
22天前
|
Linux Shell 网络安全
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
本指南介绍如何利用 HTA 文件和 Metasploit 框架进行渗透测试。通过创建反向 shell、生成 HTA 文件、设置 HTTP 服务器和发送文件,最终实现对目标系统的控制。适用于教育目的,需合法授权。
54 9
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
|
18天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
83 13
|
25天前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
1月前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
2月前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
18天前
|
Ubuntu Linux C++
Win10系统上直接使用linux子系统教程(仅需五步!超简单,快速上手)
本文介绍了如何在Windows 10上安装并使用Linux子系统。首先,通过应用商店安装Windows Terminal和Linux系统(如Ubuntu)。接着,在控制面板中启用“适用于Linux的Windows子系统”并重启电脑。最后,在Windows Terminal中选择安装的Linux系统即可开始使用。文中还提供了注意事项和进一步配置的链接。
40 0
|
30天前
|
存储 Oracle 安全
服务器数据恢复—LINUX系统删除/格式化的数据恢复流程
Linux操作系统是世界上流行的操作系统之一,被广泛用于服务器、个人电脑、移动设备和嵌入式系统。Linux系统下数据被误删除或者误格式化的问题非常普遍。下面北亚企安数据恢复工程师简单聊一下基于linux的文件系统(EXT2/EXT3/EXT4/Reiserfs/Xfs) 下删除或者格式化的数据恢复流程和可行性。
|
6月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能