[英]Multithread Directory and File Search
我是信號量和互斥概念的新手。 我應該使用多線程通過目錄在文件中遞歸文本搜索。 線程數由用戶提供。
此代碼的問題在於它通過一個目錄然后等待。 我不知道出了什么問題。我收到了分段錯誤錯誤。 無法弄清楚為什么會發生這種情況。
#include <iostream>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fstream>
#include <limits.h>
#include <stdlib.h>
#include <semaphore.h>
using namespace std;
#include <stdio.h>
int iDirectories=0;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
sem_t semaphore1;
char searchStringThread[PATH_MAX];
int directories=0;
class directoryQueue
{
private:
struct Node
{
char directoryPath[PATH_MAX];
Node *next;
};
Node *front;
Node *rear;
Node *nodeCount;
public:
directoryQueue(void)
{
front=NULL;
rear=NULL;
nodeCount=0;
}
void Enqueue(char array[PATH_MAX])
{
Node *newNode;
newNode=new Node;
strcpy(newNode->directoryPath,array);
newNode->next=NULL;
if(isEmpty())
{
front=newNode;
rear=newNode;
}
else
{
rear->next=newNode;
rear=newNode;
}
nodeCount++;
}
char * Dequeue(void)
{
Node *temp;
if (isEmpty())
cout << "Error ! Empty Queue "<<endl;
else
{
char *deque;
deque=new char[PATH_MAX];
strcpy(deque,front->directoryPath);
temp = front->next;
front = temp;
nodeCount--;
return deque;
}
}
bool isEmpty(void)
{
if(nodeCount)
return false;
else
return true;
}
void makeNull(void)
{
while(!isEmpty())
{
Dequeue();
}
}
~directoryQueue(void)
{
makeNull();
}
};
directoryQueue saveDirectory;
void *threadHandler(void *)
{
int thpath_length;
char thPath[PATH_MAX];
char saveITDirectory[PATH_MAX];
char itDirectory[PATH_MAX];
int threadCount;
struct dirent *iWalker;
DIR *iDirectory;
pthread_mutex_lock(&mutex);
threadCount=iDirectories++;
pthread_mutex_unlock(&mutex);
sem_wait(&semaphore1);
pthread_mutex_lock(&mutex);
strcpy(itDirectory,saveDirectory.Dequeue());
pthread_mutex_unlock(&mutex);
iDirectory=opendir(itDirectory);
if(iDirectory==NULL)
{
cout<<"Error"<<endl;
cout<<itDirectory<<" Cannot be Opened"<<endl;
exit(10000);
}
while((iWalker=readdir(iDirectory)) !=NULL)
{
if(iWalker->d_type==DT_REG)
{
strcpy(saveITDirectory,iWalker->d_name);
cout<<itDirectory<<"/"<<endl;
if (strcmp (saveITDirectory, "..") == 0 ||
strcmp (saveITDirectory, ".") == 0)
{
continue;
}
else
{
thpath_length = snprintf(thPath,PATH_MAX,"%s/%s",itDirectory,saveITDirectory);
cout<<thPath<<endl;
if (thpath_length >= PATH_MAX)
{
cout<<"Path is too long"<<endl;
exit (1000);
}
ifstream openFile;
openFile.open(thPath);
char line[1500];
int currentLine = 0;
if (openFile.is_open()) {
while (openFile.good()) {
currentLine++;
openFile.getline(line, 1500);
if (strstr(line, searchStringThread) != NULL){
cout<<thPath<<": "<<currentLine<<": "<<line<<endl;
cout<<"This was performed by Thread no. "<<threadCount<<endl;
cout<<"ID :"<<pthread_self();
}
}
}
openFile.close();
}
}
if (closedir (iDirectory))
{
cout<<"Unable to close "<<itDirectory<<endl;
exit (1000);
}
}
}
void walkThroughDirectory(char directory_name[PATH_MAX],char searchString[PATH_MAX])
{
DIR * directory;
struct dirent * walker;
char d_name[PATH_MAX];
int path_length;
char path[PATH_MAX];
directory=opendir(directory_name);
if(directory==NULL)
{
cout<<"Error"<<endl;
cout<<directory_name<<" Cannot be Opened"<<endl;
exit(10000);
}
while((walker=readdir(directory)) !=NULL)
{
strcpy(d_name,walker->d_name);
cout<<directory_name<<"/"<<endl;
if (strcmp (d_name, "..") == 0 ||
strcmp (d_name, ".") == 0)
{
continue;
}
else
{
path_length = snprintf(path,PATH_MAX,"%s/%s",directory_name,d_name);
cout<<path<<endl;
if (path_length >= PATH_MAX)
{
cout<<"Path is too long"<<endl;
exit (1000);
}
if(walker->d_type==DT_DIR)
{
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(path);
pthread_mutex_lock(&mutex);
sem_post(&semaphore1);
directories++;
walkThroughDirectory (path,searchString);
}
else if(walker->d_type==DT_REG)
{
ifstream openFile;
openFile.open(path);
char line[1500];
int currentLine = 0;
if (openFile.is_open()) {
while (openFile.good()) {
currentLine++;
openFile.getline(line, 1500);
if (strstr(line, searchString) != NULL)
cout<<path<<": "<<currentLine<<": "<<line<<endl;
}
}
openFile.close();
}
}
}
if (closedir (directory))
{
cout<<"Unable to close "<<directory_name<<endl;
exit (1000);
}
}
int main(int argc,char *argv[])
{
char * name;
cout<<"Total Directories "<< directories<<endl;
name=get_current_dir_name();
cout<<"Current Directory is: "<<name<<endl;
sem_init(&semaphore1,0,0);
strcpy(searchStringThread,argv[1]);
int number_of_threads=atoi(argv[3]);
pthread_t threads[number_of_threads];
walkThroughDirectory(argv[2],argv[1]);
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(argv[2]);
pthread_mutex_unlock(&mutex);
sem_post(&semaphore1);
for(int i=0;i<number_of_threads;i++)
{
pthread_create(&threads[i],NULL,threadHandler,NULL);
}
for(int j=0;j<number_of_threads;j++)
{
pthread_join(threads[j],NULL);
}
while(saveDirectory.isEmpty())
{
cout<<"Queue is Empty"<<endl;
cout<<"Exiting"<<endl;
exit(10000);
}
free(name);
cout<<"Total Directories "<< directories<<endl;
return 0;
}
有一個簡單的錯誤,您將互斥鎖鎖定兩次而不是在完成后解鎖它:
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(path);
pthread_mutex_lock(&mutex);
應該:
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(path);
pthread_mutex_unlock(&mutex);
注意:這並不是說沒有其他問題 - 只是這可能是您的直接問題。
最大的問題是,看起來您將目錄放在saveDirectory
隊列中(因此另一個線程可以將其拉下來以對其進行處理),然后在將其放入隊列的線程中遞歸處理該目錄。 我認為您需要更多地考慮如何在線程之間分配工作。
一些更小的評論:
std::string
。 它應該使您的一些字符串處理更簡單(例如,您從directoryQueue::Dequeue()
返回的數據中泄漏內存)directoryQueue
類存在的主要原因是為多個線程保存工作項,那么也許它應該管理自己的互斥鎖,這樣調用者就不需要處理這種復雜性
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.