The program I am working on is called myfile - It should find a file in a certain searchpath. You should also be able to search for multiple files and if so, I MUST create multiple child processes with fork(). The problem is, i dont get the expected outcome printed out. If I am searching for multiple files, only the first file gets "returned". I think it has something todo with the second for in the else statement. For debugging I am printing out every PID of the child processes. Is the problem maybe that the child processes are working with the same variables at the same time?
The Code: `
#include<iostream>
#include<dirent.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
using namespace std;
int main(int argc, char** argv)
{
struct dirent *d;
DIR *dr;
dr = opendir(argv[1]);
pid_t pid;
int numberOfFiles = argc - 2;
if(dr!=NULL){
if(numberOfFiles == 1){
// normal search without fork
for(d=readdir(dr); d!=NULL; d=readdir(dr)){
if(strcmp(d->d_name, argv[argc-1]) == 0){
cout << "<" << getpid() << ">: " << argv[argc-1] << ": <" << realpath(argv[argc-1], NULL) << ">" <<endl;
}
}
}else{
// search with fork
for(int i = 2; i < argc; i ){
if(fork() == 0){
cout << "Current PID: " << getpid() << " " << argv[i] <<endl;
for(d=readdir(dr); d!=NULL; d=readdir(dr)){
if(strcmp(d->d_name, argv[i]) == 0){
cout << "Current i=" << i << " "<< "<" << getpid() << ">: " << argv[i] << ": <" << realpath(argv[i], NULL) << ">" <<endl;
}
}
exit(0);
}
}
for(int i=0; i < numberOfFiles; i ){
wait(NULL);
}
}
}else
cout<<"\nError Occurred!"<<endl;
cout<<endl;
return 0;
}
` Screenshot of output in terminal:
The problem is, i dont get the expected outcome printed out. If I am searching for multiple files, only the first file gets "returned". I think it has something todo with the second for in the else statement. For debugging I am printing out every PID of the child processes. Is the problem maybe that the child processes are working with the same variables at the same time?
CodePudding user response:
Looks like a problem with opendir
, readdir
, and reusing variables. I cut your program down to:
int main(int argc, char **argv)
{
struct dirent *d;
DIR *dr;
dr = opendir(argv[1]);
for (int i = 2; i < argc; i )
{
if (fork() == 0)
{
cout << "Current PID: " << getpid() << " " << argv[i] << endl;
for (d = readdir(dr); d != NULL; d = readdir(dr))
{
cout << getpid() << "\t" << d->d_name << endl;
}
exit(0);
}
}
for (int i = 0; i < argc - 2; i )
wait(NULL);
}
And got this output (from ./testfork ../bla 1 2
):
Current PID: 17197 1
Current PID: 17198 2
17198 test.txt
17198 ..
17198 .
Which shows that once one process has read to end with readdir
, then the other gets nothing. However, if I move the call to opendir
to after the fork
:
int main(int argc, char **argv)
{
struct dirent *d;
DIR *dr;
for (int i = 2; i < argc; i )
{
if (fork() == 0)
{
dr = opendir(argv[1]); // <- Here
cout << "Current PID: " << getpid() << " " << argv[i] << endl;
for (d = readdir(dr); d != NULL; d = readdir(dr))
{
cout << getpid() << "\t" << d->d_name << endl;
}
exit(0);
}
}
for (int i = 0; i < argc - 2; i )
wait(NULL);
}
The the output becomes:
Current PID: 17751 1
17751 test.txt
17751 ..
17751 .
Current PID: 17752 2
17752 test.txt
17752 ..
17752 .
I don't quite understand why this happens, since the way fork
works should ensure that each process get their own copy of the memory (though possibly only after writing to it). So when one process modifies dr
, then that change should not be reflected in the other processes.
Perhaps it is due to dr
actually being changed through system calls (by way of readdir
), and not by the process directly?