我正在尝试实现一个线程池,并且在获取我应该使用的文件路径以比它们存在于 ftw 的 OnOpen 函数中的临时实例更永久地存储时遇到了很多麻烦. 我不允许对每个处理的文件路径执行 malloc。
这是我目前必须尝试让 OnOpen 不向我的线程提供临时数据的方法,我对它在 memcpy 上崩溃的原因感到困惑。
我很想知道如何在不创建多余的 char* 数组的情况下从正在编辑的临时变量中获取数据以确保数据安全,而我使用它来执行 memcpy。
typedef struct Task{
void (*taskFunc)(char*);
char* arg;
} Task;
void HashFunc(char* arg)
{
pthread_mutex_lock(&lock);
printf("%s\n", arg);
thingsDone++;
pthread_mutex_unlock(&lock);
}
static int OnOpen(const char* path, const struct stat* sb, int flags)//will send folder paths too
{
if(strstr(path, ".exe") || strstr(path, ".cfg")) return 0;
Task t = {
.taskFunc = &HashFunc,
.arg = path
};
memcpy(t.arg, path, strlen(path));
while(taskCount == MAX_OPEN_FILE_HANDLES-1); //busy wait
submitTask(t);
return 0;
}
编辑:很好的反馈,但这不是我所需要的。
下面我将添加一些与我遇到问题的代码相关的内容,即线程池以及我如何使用任务结构,这可能有助于更好地理解可以做什么以及我如何可以去做:
void executeTask(Task* task) {task->taskFunc(task->arg);}
void* threadFunc(void* arg)
{
Task task;
while (!(doneSending==1 && thingsDone == thingsToDo))
{
pthread_mutex_lock(&lock);
while (taskCount==0 && doneSending==0) {pthread_cond_wait(&condQueue, &lock);}
task = taskQueue[0];
for (int i = 0; i < taskCount-1; i++) {taskQueue[i] = taskQueue[i+1];}
taskCount > 0 ? --taskCount : 0;
pthread_mutex_unlock(&lock);
if (doneSending==0 || thingsDone<thingsToDo) executeTask(&task);
printf("%d, %d, %d, %d\n", taskCount, thingsDone, thingsToDo, doneSending);
}
}
void submitTask(Task task)
{
pthread_mutex_lock(&lock);
taskQueue[taskCount++] = task;
++thingsToDo;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&condQueue);
}
我的线程池由 8 个线程组成,这也是我的 taskQueue 的大小。
我曾经有,.arg = strcpy(temp, path)
但由于 temp 是临时的,我在 hashFunc 中打印了错误的数据。
每个线程都应该有自己的 Task 结构副本可以使用,以免它们相互干扰。
最终编辑:我让它工作了,这是它需要的样子:
volatile int taskIdx = 0, pathIdx = 0;
Task taskArray[MAX_OPEN_FILE_HANDLES];
char* pathQueue[MAX_OPEN_FILE_HANDLES];
void* threadFunc(void* args)
{
Task task;
while (!(doneSending==1 && taskIdx == pathIdx))
{
if (doneSending && taskIdx==pathIdx) break;
pthread_mutex_lock(&lock);
pthread_cond_wait(&condArray, &lock);
if (doneSending && taskIdx==pathIdx)
{
pthread_mutex_unlock(&lock);
break;
}
task = taskArray[taskIdx];
taskIdx = (taskIdx+1)%MAX_OPEN_FILE_HANDLES;
pthread_mutex_unlock(&lock);
executeTask(&task);
}
}
void submitTask(Task t)
{
pthread_mutex_lock(&lock);
taskArray[pathIdx] = t;
pathIdx = (pathIdx+1)%MAX_OPEN_FILE_HANDLES;
pthread_cond_signal(&condArray);
pthread_mutex_unlock(&lock);
}
static int OnOpen(const char* path, const struct stat* sb, int flags)
{
if(flags != FTW_F || strstr(path, ".cfg") || strstr(path, ".exe") || strstr(path, ".vscode") || strstr(path, "anticheat") || strstr(path, "Makefile")) return 0;
if (thingsToDo-thingsDone == MAX_OPEN_FILE_HANDLES) HashFunc((char*)path, thingsToDo++);
else
{
Task t = {
.taskFunc = &HashFunc,
.filePath = strcpy(pathQueue[pathIdx], path)
};
submitTask(t);
}
return 0;
}
int main()
{
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&condArray, NULL);
for (int i=0; i<MAX_OPEN_FILE_HANDLES; i++)
{
if(pthread_create(&pool[i], NULL, &threadFunc, NULL) != 0) perror("pth_create");
pathQueue[i] = calloc(MAX_PATH_LENGTH, sizeof(char));
}