logo资料库

线程并发拷贝程序实验报告及实验结果.doc

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
附录一 程序代码
附录二 实验结果
附录一 程序代码 #include #include #include #include #include #include #define PSIZE 4096 /*管道文件的大小*/ #define BSIZE 128 /*默认缓冲区的大小*/ #define NOFILE 20 /*u_ofile 表可分配的个数*/ #define NFILE 20 #define NPIPE 20 /*进程的 u_file 表*/ int u_ofile[NOFILE]; /*模拟 file 表*/ struct { /*p_file 表可分配的个数*/ /*p_fcb 可分配的个数*/ char f_flag;/*读写标志,'w'表示写,'r'表示读*/ int f_count;/*表示此表项的状态,=0 表示此表项没被使用,可分配;=1 表示此表项在 被使用,不可再分配*/ int f_inode;/*对应的 p_fcb 表下标*/ long f_offset;/*读写指针,当前已读或已写个数*/ }p_file[NFILE]; /*管道控制块*/ struct { char *p_addr;/*管道文件基地址*/ int p_size;/*管道文件大小,PSIZE*/ int p_count;/*=2 表示读写都在被进行,=1 表示在被读或被写,=0 表示管道没被使用, 可分配*/ }p_fcb[NPIPE]; /*模拟管道文件*/ char *pfile; /*管道的写入写出端*/ int fd[2]; /*锁机制,实现互斥*/ pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; /*进程间通信,实现同步*/ pthread_cond_t rflag = PTHREAD_COND_INITIALIZER;/*读信号量*/ pthread_cond_t wflag = PTHREAD_COND_INITIALIZER;/*写信号量*/ /*线程创建函数只能传一个参数,用结构体来封装所有参数*/ 1 / 8
struct arg_set { char *fname; int f; /*文件名*/ /*传递 fdp[]*/ }; /*u_ofile 表初始化*/ int u_ofile_init() { int i; for(i=0;i=NOFILE) { printf("u_ofile 分配失败\n"); return -2; } pfile = (char *)malloc(PSIZE*sizeof(char));/*申请模拟管道用的内存空间*/ 2 / 8
if(pfile==NULL)/*申请可能不成功*/ { return -1; } for(i=0;i=NFILE) { return -1; } for(i=0;i
if(i>=NPIPE) { return -1; } return 0;/*分配成功*/ } /*关闭管道*/ /int p_close(int a[]) { char *p; int i; for(i=0;i<2;i++) { p=p_fcb[p_file[u_ofile[a[i]]].f_inode].p_addr; if(p!=NULL) free(p); /*释放管道内存*/ p_fcb[p_file[u_ofile[a[i]]].f_inode].p_count = 0; /*管道控制块计数清零*/ p_file[u_ofile[a[i]]].f_count = 0; /*file 表项计数清零*/ u_ofile[a[i]] = -1; /*u_ofile 表项清空*/ a[i] = -1; /*fdp[]清空?/ } return 0; } /*写管道*/ int writep(int fd,char *ca,int n) { long offr,offw;/*读写指针,实际是读写字符个数*/ int r;/*管道文件读端*/ int m;/*若 ca 中的字符不能一次写完,m 用来表示一次可写入的字符的最大数*/ int w = u_ofile[fd];/*管道文件写端*/ int pf = p_file[w].f_inode;/*读管道对应的 p_fcb 表的下标*/ int n1 = n;/*一次应该写入的字符个数*/ int wstart = 0;/*计数器,写入字符个数*/ int i = 0 for(i;i
} } pthread_mutex_lock(&lock);/*互斥锁,相当于进入临界区*/ offr = p_file[r].f_offset;/*赋值读指针*/ offw = p_file[w].f_offset;/*赋值写指针*/ if((offw+n1-PSIZE)>offr)/*不能一次写完*/ { if(p_fcb[pf].p_count==0)/*对文件的复制操作已进行结束,管道文件被释放*/ { return 0; } else { m = PSIZE+offr-offw;/*最多可写入数*/ for(wstart=0;wstart
{ long offr,offw;/*读写指针,实际是读写字符个数*/ int w;/*管道文件写端*/ int m;/*若 ca 中的字符不能一次读完,m 用来表示一次可读出的字符的最大数*/ int r = u_ofile[fd];/*管道文件读端*/ int pf = p_file[r].f_inode;/*读管道对应的 p_fcb 表的下标*/ int rstart = 0;/*计数器,读出字符个数*/ int i = 0; for(i;i
offr++; } p_file[r].f_offset = offr;/*重定位读指针位置*/ pthread_cond_signal(&wflag); pthread_mutex_unlock(&lock); return m; } /*线程调用,读源文件,写管道*/ void *pwrite(void *a) { char abuf1[BSIZE]; struct arg_set *args=(struct arg_set *)a;/*需要传入多个参数时,用结构体传*/ int fdr; int n_r;/*管道文件写入字符数*/ if((fdr=open(args->fname,O_RDONLY))!=-1) { while((n_r=read(fdr,abuf1,BSIZE))>0)/*读文件,写管道*/ writep(args->f,abuf1,n_r); p_fcb[p_file[u_ofile[args->f]].f_inode].p_count--;/*文件已读完,关闭管道写端*/ } else { perror(args->fname);/*打开源文件可能不成功*/ } return NULL; } /*线程调用,写目标文件,读管道*/ void *pread(void *a) { char abuf2[BSIZE];/*缓冲区*/ struct arg_set *args=(struct arg_set *)a;/*需要传入多个参数时,用结构体传*/ int fdw; int n_w;/*管道文件读出字符数*/ if((fdw=open(args->fname,O_CREAT|O_RDWR,0777))!=-1) { while((n_w=readp(args->f,abuf2,BSIZE))>0)/*读管道,写文件*/ write(fdw,abuf2,n_w); } else { perror(args->fname);/*打开目标文件可能出错*/ } return NULL; } 7 / 8
/*主函数*/ int main(int argc,char *argv[]) { int x; u_ofile_init(); while((x=ppipe(fd))==-1);/*创建管道,即申请空间*/ if(x==-2) return -1; pthread_t t; struct arg_set args[2];/*用结构体传写线程需要的参数:文件名,管道文件读写端*/ args[0].fname=argv[1];/*源文件名*/ args[0].f=fd[1];/*管道文件写端*/ args[1].fname=argv[2];/*目标文件名*/ args[1].f=fd[0];/*管道文件读端*/ pthread_create(&t,NULL,pwrite,(void *)&args[0]);/*创建子线程,写管道*/ pread((void *)&args[1]);/*主线程调用,读管道*/ pthread_join(t,NULL);/*等待写线程结束*/ p_close(fd); return 0; } 附录二 实验结果 1. 小型文本文件测试: 2. 中型文本文件测试: 3. 大型文本文件测试: 4. 生成的目标文件与源文件的比较: 8 / 8
分享到:
收藏