我试图在c中制作一个目录监控程序。到目前为止,它检测主目录的子目录,但是当我试图监控子目录的子目录时,问题就发生了。
char * const son[] = { argv[0], name, NULL };
pid_t pid = fork();
if (pid == 0) {
execvp(son[0], son);
}
这段代码应该创建一个子进程来监视子目录。例如,name
为字符串,子目录为"Desktop/test"。我之前试着打印"name",它是我想要的子目录,所以问题不在这里。
程序运行完美,直到我添加这个。一旦我添加了它,它就会进入一个无限循环,尽管之前是有效的。我还想指出,我不使用信号,所以问题不是来自信号。
这当然只是代码的摘录。如果你认为我需要发布完整的代码,这是大得多,我会添加它,虽然老实说我怀疑问题是在它,因为它以前工作得很好。
编辑:最好添加所有的代码,argv[1]是目录,argv[2]表示我希望程序运行多少分钟,argv[3]表示每次扫描之间的暂停时间。如果我删除上面的摘录,它可以工作,我知道这有点令人困惑,但如果你有任何问题,请说。
int main(int argc, char *argv[]) {
char** direc;
int direct_pos = 0;
direc = (char**) malloc(2 * sizeof(char*));
double actual_time = 0;
double MAXTIME = atof(argv[2]);
MAXTIME = MAXTIME * 60;
double IterationTime = atof(argv[3]);
time_t start = time(0);
char dot2[100];
char dot[100];
sprintf(dot, "%s/.", argv[1]);
sprintf(dot2, "%s/..", argv[1]);
direct_pos++;
direc[direct_pos - 1] = (char*) malloc(strlen(dot) * sizeof(char));
strcpy(direc[direct_pos - 1], dot);
direct_pos++;
direc[direct_pos - 1] = (char*) malloc(strlen(dot2) * sizeof(char));
strcpy(direc[direct_pos - 1], dot2);
if (argc != 4) {
fprintf(stderr, "Usage: %s dir_namen", argv[0]);
exit(1);
}
while (actual_time < MAXTIME) {
DIR *dirp;
if ((dirp = opendir(argv[1])) == NULL) {
perror(argv[1]);
exit(2);
}
struct stat stat_buf;
struct dirent *direntp;
while ((direntp = readdir(dirp)) != NULL) {
char name[100];
sprintf(name, "%s/%s", argv[1], direntp->d_name);
if (lstat(name, &stat_buf) == -1)
{
perror("lstat ERROR");
exit(3);
}
if (S_ISDIR(stat_buf.st_mode))
{
int x;
for (x = 0; x <= direct_pos; x++) {
if (x == direct_pos) {
char**newarray;
newarray = (char**) malloc((direct_pos + 1)* sizeof(char*));
int l;
for (l = 0; l < direct_pos; l++) {
//printf("nxxxx%dn", sizeof(direc[l]));
newarray[l] = (char*) malloc((strlen(direc[l])+1)
* sizeof(char));
strcpy(newarray[l], direc[l]);
}
direc = newarray;
direc[direct_pos] = (char*) malloc(sizeof(name)
* sizeof(char));
direc[direct_pos] = strcpy(direc[direct_pos], name);
direct_pos++;
double seconds_since_start = difftime(time(0), start);
double new_time = (MAXTIME - seconds_since_start) / 60;
char time_array[10];
sprintf(time_array,"%f",new_time);
char * const son[] = { argv[0], name, time_array,
argv[3], NULL };
printf("n%sn",son[1]);
x = direct_pos + 2;
pid_t pid = fork();
if (pid == 0) {
execvp(son[0], son)==-1);
break;
}
} else if (strcmp(name, direc[x]) == 0) {
x = direct_pos + 2;
}
}
}
}
sleep(IterationTime);
actual_time += IterationTime;
closedir(dirp);
}
exit(0);
}
您有一个程序分叉,然后运行它自己的新副本。把它想象成无穷递归。不需要执行新实例,只需编写代码,以便程序根据返回的进程ID从两条路径中选择一条继续执行。
但这不是正确的解决方案。
正确的解决方案是根本不分叉。与查看1000个目录的单个进程相比,使用1000个进程查看一个目录几乎没有任何好处。实际上,如果将负载放在调度器上,情况可能会更糟。
看起来无论如何你总是分叉。我要在这里加个检查以确保当前目录下没有子目录时不会分叉
您正在分叉子进程,但是父进程在调用fork()?
后做什么?似乎您想要递归地分叉进程,但为了使其正常工作,您将不得不做以下事情:
1)检查当前目录下是否有子目录…如果没有,则读取exit()
,否则读取当前目录下的所有子目录
2)对于每个子目录fork一个进程。如果fork是子进程(即pid == 0
),则调用execvp()
。
3)如果pid != 0
,那么您在父进程中。与其尝试休眠一段时间,不如调用wait()
,并不断重复对wait()
的调用,直到没有子进程剩余。
4)一旦没有子进程(即,wait()
返回一个错误状态,errno == ECHILD
),那么你可以在父进程中调用exit()
。
所以如果你遵循这4个步骤,你应该不会产生任何无限循环。当每个子进程到达一个没有子目录的目录时,它们都会在某个时候退出,而每个父进程在退出之前都会等待它的子进程,这样就不会出现孤立的进程。如果你确实以一个无限循环结束,那是因为一个子进程没有退出,这将指向用于检测当前目录中是否有任何子目录的逻辑,或者你没有正确检测到在父进程中不再有任何子进程等待。
希望有帮助,
杰森