Linux进程通信:进程组 & 会话

1. 进程组

(1)概念:一个或多个进程的集合,也称为“作业”。

(2)父进程创建子进程时,默认属于同一个进程组。进程组ID为组长进程ID。

(3)进程组中只要有一个进程存在,进程组就存在,与组长进程是否终止无关。

(4)父子进程可不属于同一进程组。


进程组相关函数

(1)getpgrp函数

#include<unistd.h>

pid_t getpgrp(void);
/*
功能:
    获取当前进程的进程组ID
返回值:
    总是成功。
*/

(2)getpgid函数

#include<unistd.h>

pid_t getpgid(pid_t pid);
/*
功能:
    获取指定进程的进程组ID
参数:
    pid:进程号;若为0,则功能和getpgrp一样
返回值:
    成功:进程组ID
    失败:-1
*/

(3)setpgid函数

#include<unistd.h>

int setpgid(pid_t pid, pid_t pgid);
/*
功能:
    将进程pid的进程组改为pgid;可创建新的进程组
返回值:
    成功:0
    失败:-1
*/

2. 会话

概念:一个或多个进程组的集合。

创建会话注意事项:

(1)组长进程不能创建会话,否则返回出错;

(2)创建会话的非组长进程变成新会话的首进程(session header,也称为会长进程),同时会创建一个新进程组并成为组长进程(因为新会话中至少要有一个进程组);

(3)组长进程不会成为新会话首进程,新会话首进程会成为组长进程;

(4)需要root权限(Ubuntu等除外);

(5)新会话丢弃原有控制终端,该会话无控制终端;

(6)创建新会话时:先调用fork,父进程终止,子进程调用setsid(创建会话函数);

会话相关函数:

(1)getsid函数:

#include<unistd.h>

pid_t getsid(pid_t pid);
/*
功能:
    获取进程所属的会话
参数:
    pid:进程号;若为0则表示查看当前进程的会话ID
返回值:
    成功:会话ID
    失败:-1
*/

getsid示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main(int argc, const char* argv[]) {

    pid_t pid = -1;

    // 获取当前进程组会话ID
    pid = getsid(0);
    if (-1 == pid) {
        perror("getsid");
        return 1;
    }

    printf("当前进程的会话ID:%d\n", pid);

    return 0;
}

运行结果:

(2)setsid函数

#include<unistd.h>

pid_t setsid(void);
/*
功能:
    创建新会话,并用自己的ID设置为新进程组ID和新会话ID;
    该进程将成为新进程组组成和新会话会长。
返回值:
    成功:新会话ID;
    失败:-1.
*/

setsid示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main(int argc, const char* argv[]) {

    pid_t pid = -1;

    printf("父进程pid:%d\n", getpid());
    printf("父进程所属进程组的组长进程pid:%d\n", getpgrp());
    printf("父进程所属会话的会长进程pid:%d\n", getsid(0));

    // 创建新会话
    printf("父进程%d即将创建新会话...\n", getpid());
    pid = setsid(); // 失败
    if (-1 == pid) {
        printf("创建失败!父进程为组长进程,组长进程不可创建新会话..\n");
        perror("setsid");
    }

    pid = fork();
    if (-1 == pid) {
        perror("fork");
        return 1;
    }

    if (0 == pid) {  // 子进程
        printf("\n子进程创建成功!其pid:%d,其组长进程:%d\n", getpid(), getpgrp());
        printf("子进程%d即将创建新会话...\n", getpid());
        pid = setsid(); // 创建会话
        if (-1 == pid) {
            perror("setsid");
            return 1;
        }
        printf("子进程创建新会话成功\n");
        printf("子进程所属进程组的组长进程pid:%d\n", getpgrp());
        printf("子进程所属会话的会长进程pid:%d\n", getsid(0));
        printf("子进程的父进程pid:%d\n", getppid());
    } else {
        sleep(2);
        printf("\n子进程创建会话后,父进程情况:\n");
        printf("父进程所属进程组的组长进程pid:%d\n", getpgrp());
        printf("父进程所属会话的会长进程pid:%d\n", getsid(0));
        while (1) {
            sleep(1);
        }
    }
    return 0;
}

运行结果:

结果可知:

(1)组长进程不可创建新会话;

(2)非组长进程(这个示例中的子进程)创建新会话后会成为新会话的会长,同时也会创建一个新进程组并成为组长(因为新会话中至少要有一个进程组)

(3)子进程创建新会话成为新会长和新组长后,并不会影响父进程的组长和会长;

(4)父子进程可不属于同一个进程组,也可不属于同一会话。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的马师兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值