我正在尝试创建一个简单的C程序,它将调用fork
方法三次,并显示子进程的标识符(UID,GID,PID,PPID,PGID)。我正在努力正确理解真正发生的事情。我的代码中使用方法fork()
的单独方法和显示标识符,并且对于父进程,我尝试使用waitpid
方法等待所有子进程死亡。我现在真的很困惑,因为我无法让它以一种明确表示它以正确方式工作的方式工作。你能给我任何建议或更好地解决我的问题吗?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void identifiers();
void forkMethod();
int main(void)
{
forkMethod();
return 0;
}
void forkMethod()
{
int k;
int status;
for (k=0;k<3;k++){
switch (fork()) {
case -1:
perror("fork error");
exit(EXIT_FAILURE);
break;
case 0:
identifiers();
break;
default:
//wait(&status);
waitpid(getpid(), &status, WNOHANG);
sleep(1);
break;
}
}
}
void identifiers()
{
pid_t pid = getpid();
pid_t ppid = getppid();
pid_t pgid = getpgid(pid);
pid_t uid = getuid();
pid_t gid = getgid();
printf("UID:%d GID:%d PID:%d PPID:%d PGID:%d\n", uid, gid, pid, ppid, pgid);
}
// ============================================= ==============
首先,谢谢大家的答案并指出我所犯的所有错误,
我知道代码很糟糕,可能还有一些问题,但现在我觉得我有我想要的东西。
@John Bollinger问我的列表主要功能是什么: 1.编写一个显示指定进程的标识符UID,GUID,PID,PPID,PGID的函数 2.调用fork()函数3次,并为子进程显示这些标识符 3.使用睡眠功能按最旧顺序显示进程 4.根据结果显示进程树。
感谢@juhist和@Jonathan Leffler提供简明扼要的解释。如果代码中有任何重大问题,请发布
并且知道最终的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void identifiers(); // function that display identifiers
void forkMethod(); // function that calls fork() function 3 times
void tree(int); // function displaying processes tree
int main(void)
{
identifiers(); // displaying ID's for parent process
printf("Parent pid: %d\n", getpid());
printf("Child processes: \n");
forkMethod();
return 0;
}
void forkMethod()
{
int k;
int status;
int pid;
for (k=0;k<3;k++){
pid = fork();
switch (pid) {
case -1:
perror("fork error");
exit(EXIT_FAILURE);
break;
case 0:
identifiers();
exit(0);
default:
tree(getpid());
wait(&status);
sleep(1);
break;
}
}
}
void identifiers()
{
pid_t pid = getpid();
pid_t ppid = getppid();
pid_t pgid = getpgid(pid);
pid_t uid = getuid();
pid_t gid = getgid();
printf("\nUID:%d GID:%d PID:%d PPID:%d PGID:%d\n", uid, gid, pid, ppid, pgid);
}
void tree(int pid)
{
char pstree[] = "pstree -np ";
char cmd[12];
sprintf(cmd, "%s%d", pstree, pid);
system(cmd);
}
答案 0 :(得分:4)
您的一个问题出在此代码中:
case 0:
identifiers();
break;
当然,你打算这样做:
case 0:
identifiers();
exit(0);
否则子进程将继续执行,您将获得太多的分支。
另一个问题是您使用父pid而不是子pid调用waitpid()。当您使用WNOHANG参数时,这些调用没有任何用处。要么使用wait(),要么将fork的某个pid保存为fork返回,并使用该pid作为waitpid()的参数。
此外,您应该考虑检查waitpid()的返回值。在较大的程序中,如果您有信号处理程序,则可能会被信号中断调用并返回错误代码,其中包含errno == EINTR。最好重试由信号中断的系统调用,并检查其他可能的错误返回。
答案 1 :(得分:3)
在这一行:
waitpid(getpid(), &status, WNOHANG);
getpid()
将始终获得父pid,而不是孩子的pid。
建议将switch(fork())
更改为
pid= fork(); switch(pid) { ... }
和waitpid
行
waitpid(pid, &status, 0);