我有一个程序(用C11,POSIX.1-2008编写并在嵌入式Linux上运行),该程序会定期创建文件,并在一段时间后再次将其删除。
在EXT4文件系统上创建和删除文件(都是由我的程序完成)时,一切都像一个超级按钮。
现在有趣的事情发生在使用FAT32文件系统时:虽然程序能够写入文件,但是当尝试再次删除它们时,它会冻结。冻结的类型是相应的进程暂停,但不退出,并且在使用诸如top的程序查看VIRT,RES,SHR,%CPU,%MEM之类的利用率为零时。同级进程发生相同的事情,该进程与试图通过FIFO删除文件的进程通信。父进程保持活动状态。另外,文件删除发生在进程的单独线程中,因此不应停止整个进程。父进程是作为守护进程启动的,这可能就是两个孩子保持在顶部可见的原因。
|--------------|
|Parent process|
|--------------|
|
---------------------------|---------------
|| ||
\/ ||
|--------------------------------------------| ||
| Process containing file deletion | \/
||--------------------| |-------------------|| |-------------|
||File deletion thread| |Main process thread|| <- FIFOs -> |Other process|
||--------------------| |-------------------|| |-------------|
|--------------------------------------------|
如果FAT32上的目录是预先创建的(在控制台中,在其他PC上或在其他PC上),或者由程序本身使用
创建,则行为不会改变mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
我确实检查所有函数的返回值,但是没有检测到任何异常。删除调用对绝对文件名起作用。
我可以在控制台中删除文件而没有任何问题(但是程序仍然停止)。
程序以root身份运行。
有人知道为什么我有这种行为吗?
这是在文件删除线程中运行的代码:
void* _histDeleteFilesThread(void* context)
{
HistCollection* collection = ((HistThreadContext*)context)->collection;
int* retVal = ((HistThreadContext*)context)->retVal;
free(context);
*retVal = -1;
bool finished = false;
if(collection == NULL){
logging(stderr, "Bad input to runner thread\n");
pthread_exit(retVal);
}
else{
if(pthread_mutex_lock(collection->startNewSearch) != 0){
logging(stderr, "Failed to lock mutex to start a new search\n");
pthread_exit(retVal);
}
else if(sem_wait(collection->canDeleteFiles) != 0){
pthread_mutex_unlock(collection->startNewSearch);
logging(stderr, "Failed to acquire semaphore to delete files\n");
pthread_exit(retVal);
}
while(!finished){
if(pthread_mutex_lock(collection->fileDeletionDataAccess) != 0){
sem_post(collection->canDeleteFiles);
pthread_mutex_unlock(collection->startNewSearch);
logging(stderr, "Failed to acquire file deletion data access mutex\n");
pthread_exit(retVal);
}
char* file_to_delete;
if((file_to_delete = _histFIFOPop(&collection->fileToRemove)) == NULL){
finished = true;
*collection->fileDeletionThreadRunning = false;
}
else{
char* full_file_name = _histFileCreateAbsolutePath(collection, file_to_delete);
if(remove(full_file_name) != 0){
logging(stderr, "Failed to delete file %s\n", full_file_name);
finished = true;
*collection->fileDeletionThreadRunning = false;
}
else{
logging(stdout, "Removed %s\n", full_file_name);
}
free(full_file_name);
free(file_to_delete);
}
if(pthread_mutex_unlock(collection->fileDeletionDataAccess) != 0){
sem_post(collection->canDeleteFiles);
pthread_mutex_unlock(collection->startNewSearch);
logging(stderr, "Failed to lock mutex to start a new search\n");
pthread_exit(retVal);
}
}
if(sem_post(collection->canDeleteFiles) != 0){
pthread_mutex_unlock(collection->startNewSearch);
logging(stderr, "Failed to lock mutex to start a new search\n");
pthread_exit(retVal);
}
else if(pthread_mutex_unlock(collection->startNewSearch) != 0){
logging(stderr, "Failed to lock mutex to start a new search\n");
pthread_exit(retVal);
}
*retVal = 0;
pthread_exit(retVal);
}
}
简要介绍一下系统如何工作:另一个进程生成数据,该数据通过POSIX FIFO传递到包含文件删除的进程。在该过程中,首先将数据缓冲在RAM中,然后写入文件,然后将该文件的文件名存储在第一个SW FIFO中。在文件位于第一个SW FIFO中的时间内,可以搜索和使用该SW FIFO中所有文件中的数据以及缓冲区中的所有数据(所有搜索都在单独的线程中,因为它们的计算量很大,因此我们必须保持实时响应能力)。当文件变旧时,将其移至第二个SW FIFO,并启动文件删除线程。该线程必须等到所有其他搜索都终止之后再删除文件,否则它可能仍被另一个线程使用,并且直到文件删除线程删除了第二个SW FIFO中的文件后,才能开始新的搜索(文件删除线程具有更高的运行优先级(通过互斥量和信号量实现),以避免FIFO溢出。