我正在尝试做一个程序,检查蒸汽服务器列表使用叉子。我看到,如果我经常放置100.000行服务器,程序就会进入一个有线循环,并一遍又一遍地检查相同的服务器。调试之后,我看到,即使是打印服务器ip的简单程序也会出现意外情况。
计划:
#include <iostream>
#include <sys/wait.h>
#include <stdio.h>
#include <cstring>
#include <unistd.h>
#include <string>
#include <ctype.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <regex>
#include <vector>
int main(int argc, char **argv)
{
puts("Beginning program");
int max_forks = 500;
int num_forks = 0;
FILE *fpxxx = fopen("servers", "r");
if(fpxxx == NULL) {
perror("Unable to open file!");
exit(0);
}
char chunk[128];
while(fgets(chunk, sizeof(chunk), fpxxx) != NULL)
{
// puts(chunk); // same result if put the line here
if(!(fork()))
{
// sleep(3);
puts(chunk);
exit(0);
}
else
{
num_forks++;
if (num_forks >= max_forks)
{
wait(NULL);
num_forks--;
}
}
}
fclose(fpxxx);
sleep(10);
}输出:
Beginning forking
94.xxx.xxx.209
Beginning forking
184.xxx.xxx.117
Beginning forking
108.xxx.xxx.86
Beginning forking
178.xxx.xxx.140
Beginning forking
113.xxx.xxx.132
Beginning forking
45.xxx.xxx.16
... (many lines, thus servers.txt has 100.000+ ips)
# after a while i see
Beginning forking
178.xxx.xxx.140
# again and again and again
# sometimes i even see
Beginning forking
37.247.104.933.17.199.143预期产出:
94.xxx.xxx.209
184.xxx.xxx.117
108.xxx.xxx.86
178.xxx.xxx.140
113.xxx.xxx.132
45.xxx.xxx.16我是不是忘了什么?堆好像坏了。为什么我看到Beginning forking就像程序从一开始就重新运行一样?我知道分叉正在进行另一个进程,但我认为fork()从fork()的角度对程序进行了分叉。
谢谢。
编辑:解决方案是getline() is repeatedly reading the file, when fork() is used
发布于 2020-04-07 12:30:58
您在这里有几个问题:
,
fork(2)的结果。这是目前为止最严重的问题,因为你正在做100,000个叉子。如您的手册页面所示,fork()在子进程中返回0,在父进程中返回子pid,如果执行正确,则返回。但是,在您的情况下,fork()将很快给您一个错误,因为您可能无法在系统中启动10万个同时进程。如果出现错误,fork()将返回-1,并且不检查它,因此,一旦它无法生成新进程,您将以if命令的else部分结束,将错误视为父进程中的一个成功的命令叉。这很可能导致一些不好的事情。正如在回答问题的另一个答案中告诉您的那样,如果尝试调用exit(3)而不是_exit(2),您将收到很多重复的输出(缓冲区内容),因为atexit()功能不足以同时刷新父级和子级的stdio缓冲区。在终端输出中,这种情况不会发生(您不会看到这一点),因为stdio在stdout上对终端使用行缓冲,因此它会在出现fork()之前刷新缓冲区。但是,只有当输出设备是终端时,而不是如果它是一个文件(其中缓冲区只有在缓冲区已满时才被刷新,或者在退出时,所有非刷新的stdio缓冲区都被刷新)。当我假设您正在某个文件中搜索时,我假设您已经将输出重定向到一个文件,因此需要进行大量重复输出。sleep(10)调用,而是等待子进程完成,使用循环,对子进程使用wait(2)来终止,直到从wait获得错误为止。这将意味着你没有更多的孩子活着。,
stdio被一个设计得更好的库(iostream)所取代(因为新语言中新的面向对象功能,而不是说Stroustrup比Kernighan或Ritchie好,我事先表示歉意),所以,在C++中使用C/O是强烈反对的。您将从所有这些注释中看到,您的解决方案不是以调用getline()的方式解决的,因为您的代码中存在严重的问题。
发布于 2020-04-06 20:54:35
if(!(fork()))
{
// sleep(3);
puts(chunk);
exit(0);
}这应该是_exit(0);。否则,您将多次执行退出处理程序,这会对共享文件描述符等事情产生不可预测的影响。
https://stackoverflow.com/questions/61062646
复制相似问题