QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1353|回复: 9

关于多线程读文件问题(求助)

[复制链接]
发表于 2005-3-2 16:30:54 | 显示全部楼层 |阅读模式
下面是我的程序:

// linuxtest.c: Defines the entry point for the console application.
//
//#include <linux/slab.h>
//#include <linux/stat.h>
//#include <linux/fcntl.h>
//#include <linux/file.h>
//#include <linux/uio.h>
//#include <linux/smp_lock.h>
//#include <linux/dnotify.h>

//#include <asm/uaccess.h>

#include <asm/unistd.h>
#include <sys/stat.h>
//#include <string.h>
#include <fcntl.h>
//#include <stdio.h>
//#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <sys/timeb.h>
//#include <sys/types.h>
//#include <sys/resource.h>
//#include <linux/param.h>

/////////////////////////////////////////////////////////////////////////////
// The one and only application object
#define BUFFERSIZE 1024*1024*3
#define WIBLOCK 30
//char Bp2[BUFFERSIZE];
char Bp1[BUFFERSIZE];                             //读文件缓冲区
long startSeconds;                                    //开始时间(秒)
long startMilli;                                            //开始时间(微秒)
long finishSeconds;                                   //结束时间(秒)
long finishMilli;                                           //结束时间(微秒)
long rate=0;                                              //读取速度
struct timeb* timeBuffer;                           //时间缓冲区
char FName[66][8]={"1.rar","2.rar","3.rar",    //文件名数组
                                          "4.rar","5.rar","6.rar","7.rar",
                                          "8.rar","9.rar","10.rar","11.rar",
                                          "12.rar","13.rar","14.rar",
                                          "15.rar","16.rar","17.rar",
                                          "18.rar","19.rar","20.rar",
                                          "21.rar","22.rar","23.rar",
                                          "24.rar","25.rar","26.rar",
                                          "27.rar","28.rar","29.rar",
                                          "30.rar","31.rar","32.rar",
                                          "33.rar","34.rar","35.rar",
                                          "36.rar","37.rar","38.rar",
                                          "39.rar","40.rar","41.rar",
                                          "42.rar","43.rar","44.rar",
                                          "45.rar","46.rar","47.rar",
                                          "48.rar","49.rar","50.rar",
                                          "51.rar","52.rar","53.rar",
                                          "54.rar","55.rar","56.rar",
                                          "57.rar","58.rar","59.rar",
          "60.rar"};
char fileInBuffer[1024*500];                 //输出文件缓冲区
int randSelect[100];                              //文件名选取数组
long cost=0;                                          //读取消耗时间
static void *myProcess(void *arg);       //线程执行函数
//extern ssize_t sys_read(unsigned int,char*,size_t);
int consol();                                           //可变参数输入函数
int threadNum;                                      //线程标号
int totalTimes=0;                                   //读取次数
int endFlag;                                           //读取结束标志
int g_iThreadNum;                                //线程总数
int g_iFileNum;                                      //文件总数
int g_iBlockSize;                                    //块大小(每调用一次read读取块)
int g_iTotalBlocks;                                 //块数
int g_iThreadReadTimes;                       //每个线程读文件个数
int g_iSizeSelect;                                   //每个文件读取次数
pthread_mutex_t g_iMutex=PTHREAD_MUTEX_INITIALIZER; //互斥
//pthread_mutex_t g_iMutex2=PTHREAD_MUTEX_INITIALIZER;
int main()
{       
        //long buffer[32767];
        int times;
        long k;
        long f;
        char fBuffer[200];
        while(!consol()){};
        endFlag=g_iThreadNum*g_iThreadReadTimes;
        threadNum=g_iThreadNum;
        sprintf(fBuffer,"***********************************************\n             Read test in linux!           \n                %dM/PER FILE             \n***********************************************\n\0",g_iSizeSelect*g_iTotalBlocks*g_iBlockSize);
        strcat(fileInBuffer,fBuffer);
        /*srand(time((time_t*)NULL));
        for(f=0;f<g_iFileNum*(g_iThreadNum);f++)
        {
                for(k=0;k<32767;k++)
                {
                        buffer[k]=rand();
                }
                randSelect[f]=(buffer[18000])%g_iFileNum;
        }*/
        for(f=0;f<g_iFileNum;f++){
                randSelect[f]=f;
        }
        timeBuffer=(struct timeb *)malloc(sizeof(struct timeb));
        ftime(timeBuffer);
        startSeconds = timeBuffer->time;
        startMilli=timeBuffer->millitm;
        //pthread_mutex_init(&g_iMutex,PTHREAD_MUTEX_INITIALIZER);
        for(times=0;times<g_iThreadNum;times++)
        {
                pthread_t pid;
                pthread_attr_t* attr;
                struct sched_param* param;
                param=(struct sched_param*)malloc(sizeof(struct sched_param));
                attr=(pthread_attr_t*)malloc(sizeof(pthread_attr_t));
                param->sched_priority=0;
                pthread_attr_init(attr);
                pthread_attr_setscope(attr,PTHREAD_SCOPE_SYSTEM);
                //pthread_attr_setdetachstate(attr,PTHREAD_CREATE_DETACHED);
                pthread_attr_setschedpolicy(attr,SCHED_RR);
                pthread_attr_setschedparam(attr,param);
                pthread_create(&pid,attr,myProcess,NULL );
                free(attr);
                free(param);
                //setpriority(PRIO_PROCESS,pid,-20);
                //*myProcess(NULL);
        }
        sleep(999);
        //while(1){};
}

static void *myProcess(void *arg){
        //int mutexSelect;
        int download=0;
        int timeOutTimes=1;
        int perBlockRate;
        int l_iFileSize;
        int handle;
        int readTimes;
        int currentID;
        int currentTimes;
        int localEndFlag;
        int hfile;
        int k;
        int lockTimes=0;
        char *Bp;
        const char* p;
        unsigned short firstIn=1;         //Circl first in flag
        char fBuffer[WIBLOCK];
        //long start, finish;
        long ownTimeStartSeconds,ownTimeFinishSeconds,ownTimeStartMilli,ownTimeFinishMilli;
        long perFileCost=0;
        long perBlockLastSeconds=0,perBlockLastMilli=0,perBlockCurrentSeconds=0,perBlockCurrentMilli=0;
        threadNum--;
        currentID=threadNum;
        for(readTimes=0;readTimes<g_iThreadReadTimes;readTimes++){
                totalTimes++;
                currentTimes=totalTimes;
                p=FName[randSelect[readTimes*g_iThreadNum+currentID]];
                hfile=open(p,O_RDONLY);
                //Bp=(char*)malloc(BUFFERSIZE);

                ftime(timeBuffer);
                ownTimeStartSeconds = timeBuffer->time;
                ownTimeStartMilli=timeBuffer->millitm;
                for(l_iFileSize=0;l_iFileSize<g_iTotalBlocks;l_iFileSize++){
                        if(currentID>(g_iThreadNum/2-1)){
                                 pthread_mutex_lock(&g_iMutex);
                                Bp=Bp1;
                                lockTimes++;
                                //printf("\n>14 %d",currentID);
                             }
                        else {
                                pthread_mutex_lock(&g_iMutex);
                                Bp=Bp1;
                                lockTimes++;
                                //printf("\n<14 %d",currentID);
                             }
                        ftime(timeBuffer);
                        perBlockCurrentSeconds = timeBuffer->time;
                        perBlockCurrentMilli = timeBuffer->millitm;
                        if(!firstIn){
                                perBlockRate=perBlockCurrentMilli+(perBlockCurrentSeconds-perBlockLastSeconds)*1000-perBlockLastMilli;
                                if(perBlockRate>(g_iSizeSelect*g_iBlockSize*1000)){
                                perBlockRate=perBlockCurrentMilli+(perBlockCurrentSeconds-perBlockLastSeconds)*1000-perBlockLastMilli;
                                printf("\nDownload: %dM  Time of Next Block read: %ld  Timeout: %d",download,perBlockRate,timeOutTimes);
                                //sprintf(fBuffer,"\nDownload: %dM  Time of Next Block read: %ld  ",download,perBlockRate);
                                timeOutTimes++;
                                //strcat(fileInBuffer,fBuffer);
                                perBlockLastSeconds = perBlockCurrentSeconds;
                                perBlockLastMilli = perBlockCurrentMilli;
                                }
                        }else {
                                firstIn=0;
                                perBlockLastSeconds = perBlockCurrentSeconds;
                                perBlockLastMilli = perBlockCurrentMilli;
                              }
                        perBlockLastSeconds = perBlockCurrentSeconds;
                        perBlockLastMilli = perBlockCurrentMilli;
                        for(k=0;k<g_iSizeSelect;k++) read(hfile,Bp,1024*1024*g_iBlockSize);
                        if(currentID>(g_iThreadNum/2-1)) pthread_mutex_unlock(&g_iMutex);
                        else pthread_mutex_unlock(&g_iMutex);
                        download+=g_iBlockSize*g_iSizeSelect;
                        //printf("\nThread %d mutex locked  Times: %d",currentID,download);
                        sleep(0);
                }
                ftime(timeBuffer);
                ownTimeFinishSeconds = timeBuffer->time;
                ownTimeFinishMilli=timeBuffer->millitm;
                ownTimeFinishMilli+=(ownTimeFinishSeconds-ownTimeStartSeconds)*1000;
                perFileCost=ownTimeFinishMilli-ownTimeStartMilli;
                endFlag--;
                localEndFlag=endFlag;
                //sprintf(fBuffer,"\n Thread %d Filename: %s Readtimes: %d Cost: %ld",currentID,p,currentTimes,perFileCost);
                sprintf(fBuffer,"\n Thread %d ",currentID);
                //myStrCat(fileInBuffer,fBuffer,sizeof(fileInBuffer),sizeof(fBuffer));
                strcat(fileInBuffer,fBuffer);
                sprintf(fBuffer,"Filename: %s ",p);
                strcat(fileInBuffer,fBuffer);
                sprintf(fBuffer,"Readtimes: %d ",currentTimes);
                strcat(fileInBuffer,fBuffer);
                sprintf(fBuffer,"Cost: %ldms ",perFileCost);
                strcat(fileInBuffer,fBuffer);
                rate+=(g_iSizeSelect*g_iTotalBlocks*g_iBlockSize*1024*1000)/(perFileCost);
                //printf("\nLocked times: %d",lockTimes);
                printf("\nThread %d Filename: %s Readtimes: %d Cost: %ld,Average Speed is %ld K/S",currentID,p,currentTimes,perFileCost,((g_iSizeSelect*g_iTotalBlocks*g_iBlockSize*1000*1024)/(perFileCost)));
                sprintf(fBuffer,"Rate: %ldK/S\n",((g_iSizeSelect*g_iTotalBlocks*g_iBlockSize*1000*1024)/(perFileCost)));
                strcat(fileInBuffer,fBuffer);
                //free(Bp);
                close(hfile);
        }

        if(!localEndFlag) {
                ftime(timeBuffer);
                finishSeconds = timeBuffer->time;
                finishMilli=timeBuffer->millitm;
                finishMilli+=(finishSeconds-startSeconds)*1000;
                cost+=finishMilli-startMilli;
                printf("\nThread number: %d File number: %d Block size: %dM Total times:%d Cost:%8ld  \n",g_iThreadNum,g_iFileNum,g_iBlockSize,g_iThreadNum*g_iThreadReadTimes,cost);
                sprintf(fBuffer,"\nThread number: %d File number: %d ",g_iThreadNum,g_iFileNum);
                strcat(fileInBuffer,fBuffer);
                sprintf(fBuffer,"Block size: %dM Total times: %d Cost: %ldms ",g_iBlockSize,g_iThreadNum*g_iThreadReadTimes,cost);
                strcat(fileInBuffer,fBuffer);
                sprintf(fBuffer,"Avrage Rate: %ldK/S \n",(rate/((g_iThreadNum)*g_iThreadReadTimes)));
                strcat(fileInBuffer,fBuffer);
                handle = creat("history.txt", S_IREAD | S_IWRITE);
                write(handle, fileInBuffer, strlen(fileInBuffer));
                close(handle);
        }
        //while(1){};
        return NULL;
}
int consol()
{
        printf("\nIs Linuxtest2\n");                 //线程总数
        printf("\nPlease input Thread number(integer): ");
        scanf("%d",&g_iThreadNum);             //文件总数
        printf("\nPlease input fileNum(integer): ");
        scanf("%d",&g_iFileNum);
        if ((g_iFileNum)>61){ printf("\n File number must <62");return 0;}
        printf("\nPlease input blockSize(integer): ");
        scanf("%d",&g_iBlockSize);               //块大小
        printf("\nPlease input total blocks to read: ");
        scanf("%d",&g_iTotalBlocks);            //每次读的块数
        printf("\nPlease input ThreadReadTimes(per thread read times Integer type): ");
        scanf("%d",&g_iThreadReadTimes); //每个线程读文件个数
        printf("\nPlease input SizeSelect: ");
        scanf("%d",&g_iSizeSelect);             //每个文件读取次数
        return 1;
}
//文件大小=块大小*每次读的块数*每个文件读取次数


以上是小弟写的测试程序,目的是测试Linux下多线程读文件的速度

读取方式是这样的:调用系统调用read,每个文件分几次读取,利用互斥给线程加锁,这样保证同一时间内只有一个线程读文件(为了减少用于磁头移动消耗的时间),结果发现每个线程每次读取的速度很不稳定,如何让这个速度稳定些啊。
发表于 2005-3-2 16:37:35 | 显示全部楼层
这个我以前也做过,不过是两个线程对同一文件操作,一个读一个写,至于速度为什么不稳定,因为我当时的读和写操作所用的时间本来就是不一样的,所以没有考虑。我也想知道,请高手指点。
回复

使用道具 举报

 楼主| 发表于 2005-3-2 16:41:22 | 显示全部楼层
:-( 只要对同一个文件两次读取的速度不要小于1M/S就成了

我用20个线程的时候就够戗了,可是要达到30个线程才能达到要求~
回复

使用道具 举报

发表于 2005-3-2 16:47:28 | 显示全部楼层
我当时是在嵌入式系统上做的,读写速度都接近3M/S,可能跟你的进程调度有关系,想办法优化一下应该可以改善。对不起我没有创建过数十个线程来做,所以恐怕帮不了你什么忙
回复

使用道具 举报

 楼主| 发表于 2005-3-2 16:50:54 | 显示全部楼层
我做的20线程读128M文件平均速度还可以,最低的2.4M/S,可是读取的时候并不稳定时高时低,我这边的要求是:对于同一文件两次读取间隔时间/每次读取文件大小不能小于1S。
回复

使用道具 举报

 楼主| 发表于 2005-3-3 11:25:54 | 显示全部楼层
谁来帮帮俺啊
回复

使用道具 举报

发表于 2005-3-3 18:31:52 | 显示全部楼层
程序太长,没时间看,提几点。

1。不需要加锁,因为你不维护文件更新的一致性。
2。文件不一定连续放在磁盘的一个位置,可能一次读取硬盘要寻址多次
3。linux会尽可能的利用空闲的内存来做磁盘缓存,所以有的文件读取是读的内存。
4。linux不是实时操作系统,所以linux不会提供手段来保证操作的时间预测。
回复

使用道具 举报

 楼主| 发表于 2005-3-4 08:58:02 | 显示全部楼层
是啊,我就是怕磁头竞争才加的锁,试了一下,要是不加锁速度很慢~
回复

使用道具 举报

发表于 2005-3-4 12:02:15 | 显示全部楼层
[quote:79ae38d83b="nigel_d"] 是啊,我就是怕磁头竞争才加的锁,试了一下,要是不加锁速度很慢~[/quote]
那样,几个进程读几个文件速度是不是同样很慢啊,这个好象也不应该通过加锁连解决吧,按你的说法用一个进程读一个文件似乎应该更快了?
回复

使用道具 举报

 楼主| 发表于 2005-3-4 13:32:57 | 显示全部楼层
你可以写个程序试下啊~~,不同的文件散落在不同的位置上磁头移动非常频繁.磁盘会很忙.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-6 13:46 , Processed in 0.047602 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表