【发布时间】:2015-04-28 06:11:44
【问题描述】:
在为我的操作系统类编写程序时,我发现了一个有趣的案例,其中涉及似乎是涉及setpgid 的竞争条件。
分别编译下面的每个程序。执行./test 3(或任何> 2的数字)后,ps jx将显示所有infy进程已被放置在同一个组中。 ./test 2 将显示setpgid 尝试移动最后一个进程失败的错误。取消注释“修复我”行将导致 ./test 2 按预期工作。
谁能提供解释或解决方案?
// test.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
char* args[] = {
"./infy",
NULL
};
int main(int argc, char* argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s [num]\n", argv[0]);
return 1;
}
int num = strtol(argv[1], NULL, 10);
if (num < 2)
{
fprintf(stderr, "Invalid number of processes\n");
return 1;
}
pid_t pid = fork();
if (pid > 0)
{
int s;
waitpid(pid, &s, 0);
fprintf(stderr, "Children done\n");
}
else
{
pid_t pgid = -1;
int i;
for (i = 1; i < num; i++)
{
pid_t pid2 = fork();
if (pid2 > 0)
{
if (pgid == -1)
{
pgid = pid2;
}
}
else
{
if (setpgid(0, pgid == -1 ? 0 : pgid) != 0)
{
perror("setpgid failed in non-last process");
}
execve(args[0], args, NULL);
perror("exec failed");
exit(1);
}
}
// uncomment me to fix
//fprintf(stderr, "pgid %d\n", pgid);
if (setpgid(0, pgid) != 0)
{
perror("setpgid failed in last process");
}
execve(args[0], args, NULL);
perror("exec failed");
exit(1);
}
}
其中“infy”是一个单独的程序:
// infy.c
#include <unistd.h>
int main()
{
while (1)
{
sleep(1);
}
}
【问题讨论】: