UNIX进程组,会话期,作业控制

在UNIX系统中,作业控制允许在一个终端上启动多个作业(进程组),控制哪一个作业可以存取该终端,以及哪些作业在后台运行。
为了支持作业控制,引入了进程组,会话期,控制终端等概念,还需要内核以一定的信号支持。
一·进程组。
每一个进程除了有一个进程PID之外,还属于一个进程组,用进程组ID表示。返回当前进程组ID的系统调用为:

pid_t getpgrp();

每个进程组都有一个组长进程,组长进程的标识是进程组ID等于其进程ID。
进程可以调用setpgid系统调用参加一个现存的组或者创建一个新的进程组。

int setpgid(pid_t pid, pid_t pgid);

这将pid进程的进程组ID设置为pgid,如果两者相等,则pid变为进程组的组长。
一个进程只能为它自己或者它的子进程改变进程组ID,如果pid为0,则代表自己,如果pgid为0,则由pid指定的进程ID作为进程组ID。
如果pid和pgid不等,而目前系统中不存在pgid的进程组,则出错。
当用fork()产生一个子进程后,子进程将继承父进程的进程组ID,也就是子进程和父进程属于同一个进程组。

二·对话期(session)
对话期是一个或多个进程组的集合,对话期可以有一个控制终端。例如,可以由以下的安排:

进程调用setsid函数可以创建一个新的对话期。

pid_t setsid();

如果调用此函数的进程是一个进程组的组长,则出错。否则该函数创建一个新的对话期,结果为:
1)该进程变为新的对话期的首进程。
2)此进程成为一个新进程组的组长进程。新进程组的ID为调用进程的进程ID。
3)此进程没有控制终端。

三。前台进程组,后台进程组
一个对话期的几个进程组可以被分成一个前台进程组以及一个或几个后台进程组。
如果一个对话期有一个控制终端,那么它有一个前台进程组,其他进程组为后台进程组。
无论何时键入中断键(Ctrl-C)或者退出键(Ctrl-/),就会造成中断信号SIGINT或者退出信号SITQUIT送至前台进程组中的所有进程。
只有前台进程组中的进程可以接受终端输入,如果后台进程组的进程试图读终端,那么内核会发送一个特定的信号SIGTTIN给后台作业,这通常会停止(挂起)次后台作业。当用将次后台进程转为前台进程后(移入前台进程组),会发送一个SIGCONT信号给该进程,使该进程继续运行。

四·测试

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
 
int main() {
    setbuf(stdout, NULL);
 
    printf("main: %d %d/n", getpid(), getpgrp());
 
    pid_t pid = fork();
    if(pid < 0) {
        perror("fork");
        return 1;
    }   
 
    setpgid(pid, 0); 
    if(pid > 0) {
        sleep(5);
        setpgid(pid, getpgrp());
        kill(pid, SIGCONT);
        waitpid(pid, NULL, 0); 
        return 0;
    }   
 
    char buf[1024];
    printf("child: %d %d/n", getpid(), getpgrp());
    while(fgets(buf, 1024, stdin)) {
        fputs(buf, stdout);
    }   
    return 0;
}

该程序首先打印父进程的PID和进程组ID,由于该进程由shell创建,所以会将该进程的进程组ID设置为进程PID,是的该进程组属于一个新进程组,并且为前台进程组。然后fork出一个子进程,此时子进程应该继承父进程的进程组ID,和父进程同属于前台进程组,然后父子进程下一步都调用setpgid(pid, 0),这会确保把子进程设为一个新的进程组的组长,并且该进程组为后台进程组。这个时候子进程打印自己的进程PID和进程组ID,然后开始循环从终端读入一行数据,并原样输入到终端,由于这个子进程属于后台进程组,这会导致子进程被挂起(停止),所以屏幕上不会有什么输出。父进程先睡眠5秒钟(给我足够的时间来敲几行字符演示子进程确实没有输出),然后设置子进程的组ID为自己的组ID,也就是将子进程移入前台进程组,然后发送SIGCONT信号给子进程,使子进程重新运行,由于这是子进程已经属于前台进程组了,因此可以成功的读入终端字符并显示出来。

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值