如何将 pid 的值保存在数据结构中并稍后使用 fork() 访问它?

Posted

技术标签:

【中文标题】如何将 pid 的值保存在数据结构中并稍后使用 fork() 访问它?【英文标题】:How can I save the value of pid in a data structure and access it later with fork()? 【发布时间】:2021-12-17 05:39:57 【问题描述】:

我有一个程序,我在其中创建了几个不同的子进程来模拟 shell 脚本。如果进程应该在后台运行,我正在做的是创建一个子进程,然后将它的进程 ID 存储在数据库中,以便下次运行命令时,我可以使用 waitpid(pid,status,WNOHANG )。

我遇到的问题是存储子进程 ID 的值,然后尝试访问它们。

这是我创建新子进程并将它们插入到接受 void * 作为“节点”的 DLL 的代码:

typedef void*Data;

extern void execCommand(Command command, Pipeline pipeline, Jobs jobs,
                             int *jobbed, int *eof, int fg) 
  CommandRep r=command;
  if (fg && builtin(r,eof,jobs))
    return;

  int pid=fork();
  if (pid==-1)
    ERROR("fork() failed");
  if (pid==0)
    // do some work as the child
   else if(fg && pid > 0) 
    // if you're a parent and this is a foreground process
    // wait for the most recent process that started running
    // then try to wait for existing children if they exist
    int c_stat = -999;
    waitpid(pid,&c_stat,0);
    attemptWait();
   else if (fg==0 && pid > 0) 
    // if you're a parent and this is a background process
    // add this childs process id to the list, and then
    // attempt to wait for all processes to finish
    dll_put(running_processes,(Data)&pid);
    attemptWait();
  

void attemptWait() 
  int j=-999;
  for(int i=0;i<dll_len(running_processes);i++) 
    j=waitpid(*(int *)dll_ith(running_processes, i),&j,WNOHANG);
    printf("child pid: %d\n",*(int *)dll_ith(running_processes, i));
    if((j)==(*(int *)dll_ith(running_processes, i))) 
      printf("[%d]+ Done", i);
     else if (j == -1) 
      printf("there was an error closing the %d-th process\n", i);
    
  

现在,发生的事情是,当我存储新创建的子进程的 pid 时,我将 pid 的地址传递给它以存储在数据结构中,但是下次调用 execCommand 时,pid 会更新,所以所有我在 DLL 中的 pid 被覆盖了,我每次输入命令时都试图关闭同一个进程。

如何获取存储在 DLL 中的整数值,这样我就可以使用它而不用担心它会被覆盖?

【问题讨论】:

请查看***.com/help/minimal-reproducible-example。 【参考方案1】:

我不知道您正在使用的dll_..() 函数,但很明显,当execFunction() 返回时,您总是存储超出范围的局部变量的地址。因此,您应该尝试分配一个缓冲区来存储该 pid:

pid_t *pid_ptr = malloc( sizeof *pid_ptr );
*pid_ptr = pid;
dll_put(running_processes, pid_ptr);

当您不再需要该 pid 时,不要忘记致电 free()(应该在孩子终止后)

【讨论】:

甜蜜!如果 pid_ptr 与我开始存储 pid 的范围相同,是否会被覆盖,因为我正在为 malloc 分配空间? 如果它总是 sa 地址(例如静态或全局变量),它也会被覆盖。不同之处在于,在您的情况下 any 访问存储的指针会导致 UB

以上是关于如何将 pid 的值保存在数据结构中并稍后使用 fork() 访问它?的主要内容,如果未能解决你的问题,请参考以下文章