如何一次只分叉一个 child
How to fork only one child at a time
我第一次尝试分叉。我有一个包含整数列表的文件,我希望每一行都派生一个 child,child 处理该行并在输出文件中写入一些内容。基本上,for 循环从输入文件中的行数开始,然后进入一个循环,每一行都应该分叉一个 child,在完成 child 之后,分叉应该启动另一个 child。我在执行此操作时遇到了麻烦,因为在第一个 child 完成其工作之前,第二个 child 开始并且在 parent 之间也在执行一些操作。
编辑:代码看起来像这样:
void dosomething(flag)
{
}
void forkingfunction(int size, int array[],char *outputfile)
{
int i,j,starting=1,temp=1,status;
for(i=0;i<size;i++,temp++)
{
pid_t pID = fork();
if (pID == 0) // child
{
printf("\nchild pid %d\n",getpid());
const int count = dosomething(flag);
if(flag==1)
{
_exit(EXIT_SUCCESS);
kill(pID,SIGKILL);
}
else
{
FILE *fp;
fp = fopen(outputfile, "a+");
if (fp == NULL)
{perror("Unable to open the output file:");}
for (i = 0; i < len; i++)
{
if (solution[i])
{
fprintf(fp," %u ",array[i]);
}
}
fprintf(fp,"=%d\n",sum);
}
_exit(EXIT_SUCCESS);
kill(pID,SIGKILL);
}
else if (pID < 0) // failed to fork
{
perror("Failed to fork:");
}
else
{
// wait(NULL);
if ((pID = wait(&status)) == -1)
{
perror("Error in wait:");
}
}
}
}
void readingfile(char *inputfile,char *outputfile)
{
FILE *myFile = fopen(input, "r");
if (myFile == NULL)
{
perror("Error: Failed to open file.");
}
//code to get number of lines
while ((c=getc(myFile)) != EOF)
{
//puts values of file in an array for processing
}
forkingfunction(size,array,output);
// close file
fclose(myFile);
}
int main(int argc, char **argv)
{
readingfile(inputfilename,outputfilename);
return 0;
}
您使用一次调用 wait()
:
else
{
// wait(NULL);
if ((pID = wait(&status)) == -1)
{
perror("Error in wait:");
}
}
那(或改用 waitpid()
)是您问题答案的核心,但是……
您需要一个与 pID
不同的变量来保存 return 值,以确保您得到正确的死 child 因为相关的 PID 在 pID
在它被破坏之前。
如果您在该进程的后台有其他进程 运行,您可能会得到其中一个,而不是刚刚启动的 child,因此您需要测试wait()
上报的PID 是否正确,如果不正确再试。这意味着你需要一个像这样的循环:
int corpse;
int status;
while ((corpse = wait(&status)) != pID && corpse != -1) // Or corpse > 0
{
/* maybe report on what died */
}
或者可以用waitpid()
直接等相关的child死掉:
int corpse;
int status;
while ((corpse = waitpid(pID, &status, 0)) != pID && corpse != -1)
{
/* maybe report on what died */
}
如果没有 children 等待,或者指定的 PID 不再存在,wait()
和 waitpid()
调用将终止并出现错误。如果程序中其他地方的代码等待进程终止,则可能会发生这种情况。也可以处理它;当系统显示 "there are no children left" 或 "that process you asked about doesn't exist" 时,您不希望循环被锁定。如果您有 SIGCHLD
的信号处理程序并且它会等待一些时间,也会发生这种情况。
在这两种情况下,您可能需要决定如果 corpse == -1
在循环之后要做什么。它不应该发生,但是......你可以合法地决定什么都不做。
请注意,如果 parent 进程(称之为 Program1
)派生了一些 child 处理然后使用 exec*()
将其自身替换为另一个程序 Program2
。 Program2
不知道它的进程是其他 children 的 parent 进程,而不是它创建的。这合理吗?是的,可以做到;我有测试代码可以做到这一点。有可能吗?不;它需要一个不寻常的设置,但并不难做到。例如,如果 shell 脚本启动了一些后台进程,然后发出 exec program-that-forks
,派生程序的进程具有 shell 创建的后台进程 children ,即使分叉的程序没有创建这些进程。
我第一次尝试分叉。我有一个包含整数列表的文件,我希望每一行都派生一个 child,child 处理该行并在输出文件中写入一些内容。基本上,for 循环从输入文件中的行数开始,然后进入一个循环,每一行都应该分叉一个 child,在完成 child 之后,分叉应该启动另一个 child。我在执行此操作时遇到了麻烦,因为在第一个 child 完成其工作之前,第二个 child 开始并且在 parent 之间也在执行一些操作。
编辑:代码看起来像这样:
void dosomething(flag)
{
}
void forkingfunction(int size, int array[],char *outputfile)
{
int i,j,starting=1,temp=1,status;
for(i=0;i<size;i++,temp++)
{
pid_t pID = fork();
if (pID == 0) // child
{
printf("\nchild pid %d\n",getpid());
const int count = dosomething(flag);
if(flag==1)
{
_exit(EXIT_SUCCESS);
kill(pID,SIGKILL);
}
else
{
FILE *fp;
fp = fopen(outputfile, "a+");
if (fp == NULL)
{perror("Unable to open the output file:");}
for (i = 0; i < len; i++)
{
if (solution[i])
{
fprintf(fp," %u ",array[i]);
}
}
fprintf(fp,"=%d\n",sum);
}
_exit(EXIT_SUCCESS);
kill(pID,SIGKILL);
}
else if (pID < 0) // failed to fork
{
perror("Failed to fork:");
}
else
{
// wait(NULL);
if ((pID = wait(&status)) == -1)
{
perror("Error in wait:");
}
}
}
}
void readingfile(char *inputfile,char *outputfile)
{
FILE *myFile = fopen(input, "r");
if (myFile == NULL)
{
perror("Error: Failed to open file.");
}
//code to get number of lines
while ((c=getc(myFile)) != EOF)
{
//puts values of file in an array for processing
}
forkingfunction(size,array,output);
// close file
fclose(myFile);
}
int main(int argc, char **argv)
{
readingfile(inputfilename,outputfilename);
return 0;
}
您使用一次调用 wait()
:
else
{
// wait(NULL);
if ((pID = wait(&status)) == -1)
{
perror("Error in wait:");
}
}
那(或改用 waitpid()
)是您问题答案的核心,但是……
您需要一个与
pID
不同的变量来保存 return 值,以确保您得到正确的死 child 因为相关的 PID 在pID
在它被破坏之前。如果您在该进程的后台有其他进程 运行,您可能会得到其中一个,而不是刚刚启动的 child,因此您需要测试
wait()
上报的PID 是否正确,如果不正确再试。这意味着你需要一个像这样的循环:int corpse; int status; while ((corpse = wait(&status)) != pID && corpse != -1) // Or corpse > 0 { /* maybe report on what died */ }
或者可以用
waitpid()
直接等相关的child死掉:int corpse; int status; while ((corpse = waitpid(pID, &status, 0)) != pID && corpse != -1) { /* maybe report on what died */ }
如果没有 children 等待,或者指定的 PID 不再存在,wait()
和 waitpid()
调用将终止并出现错误。如果程序中其他地方的代码等待进程终止,则可能会发生这种情况。也可以处理它;当系统显示 "there are no children left" 或 "that process you asked about doesn't exist" 时,您不希望循环被锁定。如果您有 SIGCHLD
的信号处理程序并且它会等待一些时间,也会发生这种情况。
在这两种情况下,您可能需要决定如果 corpse == -1
在循环之后要做什么。它不应该发生,但是......你可以合法地决定什么都不做。
请注意,如果 parent 进程(称之为 Program1
)派生了一些 child 处理然后使用 exec*()
将其自身替换为另一个程序 Program2
。 Program2
不知道它的进程是其他 children 的 parent 进程,而不是它创建的。这合理吗?是的,可以做到;我有测试代码可以做到这一点。有可能吗?不;它需要一个不寻常的设置,但并不难做到。例如,如果 shell 脚本启动了一些后台进程,然后发出 exec program-that-forks
,派生程序的进程具有 shell 创建的后台进程 children ,即使分叉的程序没有创建这些进程。