我尝试编写我的“getpid”克隆,因为我有一个学校项目,而 getpid 是被禁止的功能。所以,我写了这段代码:
pid_t mini_getpid(void)
{
pid_t id;
id = fork();
if (id == 0)
exit(0);
else
{
wait(0);
return (id - 1);
}
}
我尝试使用 fork 函数获取主进程的 pid。但有一个问题。当我比较我的返回值和真实的 getpid() 函数时,我的函数总是返回大 1 的值。例如,如果 getpid() 的返回值是 1000,那么由于 fork 函数,我的函数会返回 1001。 fork 函数做错了什么?为什么它返回的 PID 值比应有的值大 1?
Fork 返回子进程的 PID,到目前为止,它在您的机器和环境上一直比父进程高 1,这纯粹是运气。这并不是一个保证;而是一个保证。内核可以为子进程分配任何有效的、未使用的 PID。
如果您确实需要 getpid 而不调用 getpid C 函数,您始终可以调用原始系统调用:
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
int main(void) {
pid_t pid = syscall(SYS_getpid);
pid_t pid2 = getpid(); // for comparison
printf("%d %d\n", pid, pid2);
return 0;
}
如果您的任务精神是不使用该系统调用,那么您将不得不探索提供您所需信息的其他辅助渠道。最好的方法显然取决于你在任务中可以做什么和不可以做什么。
另一种可能(但效率低下)的方法是在子进程到父进程之间建立某种通信通道(例如共享内存、管道等),并在子进程中进行
getppid
调用。
您正在对父 pid 和子 pid 之间的关系做出不应该做出的假设。子 pid 可以是任何东西,所以
child_pid - 1
不是获取父 pid 的正确方法。
如果
getpid()
是唯一被禁止的函数,您可以在子进程中使用 getppid()
(获取父进程 pid),然后通过 pipe
将其发送回父进程。
这是一个例子。添加错误检查留作练习。
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
enum { P_RD, P_WR };
pid_t mini_getpid(void) {
int fds[2];
pipe(fds); // create a pipe
pid_t id = fork();
if (id == 0) {
close(fds[P_RD]); // close the reading end of the pipe
pid_t parent = getppid(); // get parent pid
write(fds[P_WR], &parent, sizeof parent); // send it to the parent
close(fds[P_WR]); // close the writing end
exit(0);
}
// in parent process
close(fds[P_WR]); // close the writing end
read(fds[P_RD], &id, sizeof id); // read the pid written by the child
close(fds[P_RD]); // close the reading end
return id;
}