- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在为我的 OS 类编写程序时,我发现了一个有趣的案例,该案例涉及一个似乎涉及 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);
}
}
最佳答案
我终于明白了。当 setpgid
失败时,errno
被设置为 EPERM
。 EPERM
的手册页上可能出现的错误之一是:
The value of the pgid argument is valid but does not match the process ID of the process indicated by the pid argument and there is no process with a process group ID that matches the value of the pgid argument in the same session as the calling process.
这种情况下的竞争条件是子进程是否可以在父进程之前设置它的 pgid。如果 child 赢得比赛,一切都很好。如果父进程赢得了比赛,它试图设置的进程组尚不存在,setpgid
失败。
解决方案是让父进程在第一个 fork 之后立即设置子进程的组 ID,方法是在 if (pgid == -1) 中调用
block 。setpgid(pid2, pid2)
也相关,来自手册页:
To provide tighter security, setpgid() only allows the calling process to join a process group already in use inside its session or create a new process group whose process group ID was equal to its process ID.
关于c - setpgid 的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28732764/
在为我的 OS 类编写程序时,我发现了一个有趣的案例,该案例涉及一个似乎涉及 setpgid 的竞争条件。 分别编译下面的每个程序。在执行完./test 3(或任意数字> 2)后,ps jx 会显示所
我不知道为什么我的计算机上会出现这样的错误。我已经在其他一些计算机上测试了代码。效果很好。 如果我删除 sleep(2),它就会起作用。我想我应该能够为僵尸进程设置 PGID。它取决于操作系统的实现吗
我正在尝试将进程的 pgrp 更改为子进程的 pgrp,以便我可以在父进程上 setsid。唯一的问题是我不断收到 EPERM 错误代码。根据 htop,这两个进程具有相同的 session 组。 我
来自 Linux 编程接口(interface) #include int setpgid(pid_t pid , pid_t pgid ); The pid argument may not
我就是不明白。 我的进程树: 0 / \ 1 2 / \ 5 3 / 4 我想创建一个进程组(3、4、5),并向该组
当我执行这个函数时,我计算出了 setpgid() 的函数,结果将被拒绝权限。然后我当时以 root 用户身份登录,这也会打印错误消息,因为权限被拒绝。那么哪个用户可以使用这个功能。谁能给我解释一下?
根据 man setpgid(2) 页面, EACCES An attempt was made to change the process group ID of one of the childr
我正在尝试重新编写一个 shell,我想更改用我的 shell 启动的程序的 pgid! 我尝试在我的 fork() 之后执行不同的功能: setpgid(0, 0) 使诸如 vim、emacs 之类
root@arch:/ 19:27:32 # docker run -t -i ubuntu /bin/bashroot@74b77bf42943:/# lsbash: child setpgid (
我正在尝试编写一个执行子命令的程序,并且不允许该子命令被 Ctrl+C 杀死。 我读到可以使用 setpgid/setpgrp 来完成此操作。 以下代码适用于 OSX,但在 Linux(2.6.32、
我是一名优秀的程序员,十分优秀!