readdir函数使用中遇到的问题

在使用readdir函数开线程是遇到一个问题:readdir返回的结构体的内存空间被覆盖了!

 44     mList = createList();
 45     Read_DIR_mp3(PATH,mList);
 46 
 47     printf("you can use <H>or<h> to get help\n");
 48     
 49     signal(SIGCHLD,Receive);
 50     signal(SIGINT,No_Exit);
 51     srand(time(NULL));//设置随机数种子
 52 
 53     memcpy(shm_addr,pos,4096);//初始化共享内存
 54     showNode(mList);
 55 
 56     if(-1 == pthread_create(&pthread_id,NULL,(void *)thread,NULL))
 57     {
 58         perror("Pthread Create error");
 59         exit(-1);
 60     }
 61     showNode(mList); 

这一段函数中ShowNode(mList)是打印链表,Read_DIR_mp3函数用来读取指定目录下的.mp3格式的文件并放入以mList为首节点的链表中

可以看到对于同一个链表打印的内容却不同,在开启子线程后缺失了很多内容!

我的链表结点是这样定义的:

 10 typedef struct node
 11 {
 12     char *name;
 13     //char *path;
 14     struct node *peror;
 15     struct node *next;
 16 }Node;
 17 
 18 typedef struct Head_node
 19 {
 20     int length;
 21     Node *mhead;
 22 }music_List;

当我把char *name 改为char name[64]并用strcpy函数进行赋值时这一现象就消失了;进过查找发现原来readdir函数是线程非安全的。

多线程不安全函数是指:
一个进程中有很多全局变量以及函数(error、strtok、asctime等),各个线程对这些变量会产生干扰。在多线程运行期库中每个线程有自己的本地存储空间,有时也会使用全局变量和静态变量,如果多线程随意同时访问全局变量和静态变量,就将出现意向不到的错误,这个在现在的多线程编程中一般都会通过加锁等机制解决,但我们往往忽略了C run-time library里面的一些函数使用了全局变量和静态变量却没用相应机制避免冲突。

而readdir函数因为内部使用了静态数据,即readdir成功时返回指针所指向的dirent结构体是静态分配的,所以readdir被认为不是线程安全的函数,POSIX[i]标准这样描述:

         The application shall not modify the structure to which the return value of readdir() points, nor any storage areas pointed to by pointers within the structure. The returned pointer, and pointers within the structure, might be invalidated or the structure or the storage areas might be overwritten by a subsequent call to readdir() on the same directory stream. They shall not be affected by a call to readdir() on a different directory stream.

         If a file is removed from or added to the directory after the most recent call to opendir() or rewinddir(),whether a subsequent call to readdir() returns an entry for that file is unspecified.

         The readdir() function need not be thread-safe.

解决方法可以向我之前使用的采用局部变量保存数据,也可以加锁使用;当然还可以使用readdir_r函数(然而,在GNU的官方文档[ii]中还是建议使用readdir函数)。

猜你喜欢

转载自blog.csdn.net/cainiao000001/article/details/81085290