我们知道cgroup(control group)技术是基于进程组的。cgroup是Linux内核提供的一种机制,用于限制、控制和监视进程组的资源使用。通过cgroup,可以将一组进程绑定到一个cgroup中,并对该cgroup中的进程进行资源限制和监视,例如CPU、内存、磁盘I/O等。这样可以避免某些进程占用过多的系统资源,从而提高系统的稳定性和可靠性。
每一个进程都有一个进程组号(PGID)
进程组可以方便进程管理(如:同时杀死多个进程,发送一个信号给多个进程)
进程组相关api
pid_t getpgid(pid_t pid); // 获取当前进程的组标识
pid_t getpgid(pid_t pid); // 获取指定进程的组标识
int setpgid(pid_t pid, pid_t pgid); //设置进程的组标识
pid == pgid,将pid指定的进程设为组长
pid == 0,设置当前进程的组标识
pgid ==0,则将pid作为组标识
默认情况下,子进程与父进程属于同一个进程组
demo1 如下所示:
#include
#include
#include
#include
#include
int main(int argc,char* argv[]){
int pid = 0;
int i=0;
printf("parent 进程id = %d,ppid 父进程id = %d,pgid 组标识 = %d\n",getpid(),getppid(),getpgrp());
while(i < 5)
{
if((pid = fork()) >0)
{
printf("new: %d\n",pid);
}
else if(pid == 0)
{
sleep(1);
printf("child = %d,ppid = %d,gpid =%d\n",getpid(),getppid(),getpgrp());
sleep(10);
break;
}
else
{
printf("fork error...\n");
}
i++;
}
return 0;
}
编译运行输出:
wj@wj:~/WORK/Learning/DT/C++$ gcc pgid_j.c -o pgid_j.out
wj@wj:~/WORK/Learning/DT/C++$ ./pgid_j.out &
[1] 6313
parent 进程id = 6313,ppid 父进程id = 4951,pgid 组标识 = 6313
new: 6315
new: 6316
new: 6317
new: 6318
new: 6319
[1]+ 已完成 ./pgid_j.out
wj@wj:~/WORK/Learning/DT/C++$
child = 6315,ppid = 1499,gpid =6313
child = 6316,ppid = 1499,gpid =6313
child = 6317,ppid = 1499,gpid =6313
child = 6318,ppid = 1499,gpid =6313
child = 6319,ppid = 1499,gpid =6313
ps
PID TTY TIME CMD
4951 pts/0 00:00:00 bash
6315 pts/0 00:00:00 pgid_j.out
6316 pts/0 00:00:00 pgid_j.out
6317 pts/0 00:00:00 pgid_j.out
6318 pts/0 00:00:00 pgid_j.out
6319 pts/0 00:00:00 pgid_j.out
6333 pts/0 00:00:00 ps
可以看到当前进程 6313,连续创建了5个子进程,可以看到这5个子进程属于 6313 这个进程组。进程组长是 6313。
问题一:父进程为 6313 ,可是在子进程中的父进程 ppid 却是 1499?这个是怎么回事?
原因:父进程在子进程打印之前就已经结束了,然后子进程全部被收养了。父进程先结束了,那么子进程被初始化进程收养。
现在我们改一下代码,将子进程中第一行代码 sleep(1) 给注释掉。代码如下:
#include
#include
#include
#include
#include
int main(int argc,char* argv[]){
int pid = 0;
int i=0;
printf("current = %d,ppid = %d,pgid = %d\n",getpid(),getppid(),getpgrp());
while(i < 5)
{
if((pid = fork()) >0)
{
printf("new: %d\n",pid);
}
else if(pid == 0)
{
//sleep(1);
printf("child = %d,ppid = %d,pgid =%d\n",getpid(),getppid(),getpgrp()); //
sleep(10);
printf("last -- pgid = %d\n",getpgrp());
break;
}
else
{
printf("fork error...\n");
}
i++;
}
return 0;
}
再次编译运行,这次输出的结果是正常的。
wj@wj:~/WORK/Learning/DT/C++$ gcc pgid_j.c -o pgid_j.out
wj@wj:~/WORK/Learning/DT/C++$ ./pgid_j.out &
[1] 8484
current = 8484,ppid = 4951,pgid = 8484
new: 8486
new: 8487
child = 8486,ppid = 8484,pgid =8484
new: 8488
child = 8487,ppid = 8484,pgid =8484
new: 8489
child = 8488,ppid = 8484,pgid =8484
new: 8490
child = 8489,ppid = 8484,pgid =8484
child = 8490,ppid = 8484,pgid =8484
[1]+ 已完成 ./pgid_j.out
wj@wj:~/WORK/Learning/DT/C++$ last -- pgid = 8484
last -- pgid = 8484
last -- pgid = 8484
last -- pgid = 8484
last -- pgid = 8484
进程组长终止,进程组依然存在(进程组长仅用于创建新进程组)
父进程创建子进程后立即通过setpgid()改变其组标识(PGID)
同时,子进程也需要通过setpgid()改变自身组标识(PGID)
子进程调用exec()
父进程无法通过setpgid()改变其组标识(PGID)
只能自身通过setpgid()改变其组标识(PGID)
//未完待续...