您好,欢迎访问三七文档
南昌大学实验报告学生姓名:陈星任学号:6100412040专业班级:网工121班实验类型:□验证□综合□设计□创新实验日期:2015.5.10实验成绩:一、实验项目名称《文件操作》二、实验目的通过编写文件读写及上锁的程序,进一步熟悉Linux中文件I/O相关的应用开发,并且熟练掌握open()、read()、write()、fcntl()等函数的使用。三、实验内容在Linux中FIFO是一种进程之间的管道通信机制。Linux支持完整的FIFO通信机制。本实验内容,通过使用文件操作,仿真FIFO(先进先出)结构以及生产者-消费者运行模型。本实验中需要打开两个虚拟终端,分别运行生产者程序(producer)和消费者程序(customer)。此时两个进程同时对同一个文件进行读写操作。因为这个文件是临界资源,所以可以使用文件锁机制来保证两个进程对文件的访问都是原子操作。先启动生产者进程,它负责创建仿真FIFO结构的文件(其实是一个普通文件)并投入生产,就是按照给定的时间间隔,向FIFO文件写入自动生成的字符(在程序中用宏定义选择使用数字还是使用英文字符),生产周期以及要生产的资源数通过参数传递给进程(默认生产周期为1s,要生产的资源数为10个字符)。后启动的消费者进程按照给定的数目进行消费,首先从文件中读取相应数目的字符并在屏幕上显示,然后从文件中删除刚才消费过的数据。为了仿真FIFO结构,此时需要使用两次复制来实现文件内容的偏移。每次消费的资源数通过参数传递给进程,默认值为10个字符。四、实验步骤(1)实验流程图本实验的两个程序的流程图如图:(2)代码头部文件代码:mylock.hstructmyflock{shortl_type;/*文件锁类型:F_RDLOCK读取锁;F_WRLCK写入锁;F_UNLCK解锁*/off_tl_start;/*相对位移量*/shortl_whence;/*相对位移量的起点SEEK_SET;SEEK_CUR;SEEK_END:*/off_tl_len;/*加锁区域长度*/pid_tl_pid;/**/};/*lock_set*/intlock_set(intfd,inttype){structmyflockold_lock,lock;lock.l_whence=SEEK_SET;lock.l_start=0;lock.l_len=0;lock.l_type=type;lock.l_pid=-1;/*判断文件是否可以上锁*/fcntl(fd,F_GETLK,&lock);if(lock.l_type!=F_UNLCK){/*判断文件不能上锁的原因*/if(lock.l_type==F_RDLCK)/*该文件已有读取锁*/{printf(Readlockalreadysetby%d\n,lock.l_pid);}elseif(lock.l_type==F_WRLCK)/*该文件已有写入锁*/{printf(Writelockalreadysetby%d\n,lock.l_pid);}}/*l_type可能已被F_GETLK修改过*/lock.l_type=type;/*根据不同的type值进行阻塞式上锁或解锁*/if((fcntl(fd,F_SETLKW,&lock))0){printf(Lockfailed:type=%d\n,lock.l_type);return1;}switch(lock.l_type){caseF_RDLCK:printf(Readlocksetby%d\n,getpid());break;caseF_WRLCK:printf(Writelocksetby%d\n,getpid());break;caseF_UNLCK:printf(Releaselockby%d\n,getpid());return1;break;default:break;}/*endofswitch*/return0;}生产者程序的源代码:producer.c/*producer.c*/#includestdio.h#includeunistd.h#includestdlib.h#includestring.h#includefcntl.h#includemylock.h#defineMAXLEN10/*缓冲区大小最大值*/#defineALPHABET1/*表示使用英文字符*/#defineALPHABET_START'a'/*头一个字符,可以用'A'*/#defineCOUNT_OF_ALPHABET26/*字母字符的个数*/#defineDIGIT2/*表示使用数字字符*/#defineDIGIT_START'0'/*头一个数字字符*/#defineCOUNT_OF_DIGIT10/*数字字符的个数*/#defineSIGN_TYPEALPHABET/*本实例用英文字符*/constchar*fifo_file=./myfifo;/*!FIFO文件名*/charbuff[MAXLEN];/*缓冲区*//*函数product()产生一个字符并写入仿真FIFO文件中*/introduct(void){intfd;unsignedintsign_type,sign_start,sign_count,size;staticunsignedintcounter=0;/*打开!FIFO文件*/if((fd=open(fifo_file,O_CREAT|O_RDWR|O_APPEND,0644))0){printf(Openfifofileerror\n);exit(1);}sign_type=SIGN_TYPE;switch(sign_type){caseALPHABET:/*英文字符*/{sign_start=ALPHABET_START;sign_count=COUNT_OF_ALPHABET;}break;caseDIGIT:/*数字字符*/{sign_start=DIGIT_START;sign_count=COUNT_OF_DIGIT;}break;default:{return-1;}}/*endofswitch*/sprintf(buff,%c,(sign_start+counter));counter=(counter+1)%sign_count;lock_set(fd,F_WRLCK);/*上写锁*/if((size=write(fd,buff,strlen(buff)))0){printf(Producer:writeerror\n);return-1;}lock_set(fd,F_UNLCK);/*解锁*/close(fd);return0;}intmain(intargc,char*argv[]){inttime_step=1;/*生产周期*/inttime_life=10;/*需要生产的资源数*/if(argc1){/*第一个参数表示生产周期*/sscanf(argv[1],%d,&time_step);}if(argc2){/*第二个参数表示需要生产的资源数*/sscanf(argv[2],%d,&time_life);}while(time_life--){if(product()0){break;}消费者程序的源代码:customer.c/*customer.c*/#includestdio.h#includeunistd.h#includestdlib.h#includestring.h#includefcntl.h#includemylock.h#defineMAX_FILE_SIZE100*1024*1024/*100M*/constchar*fifo_file=./myfifo;/*仿真FIFO文件名*/constchar*tmp_file=./tmp;/*临时文件名*//*资源消费函数customing*/intcustoming(constchar*myfifo,intneed){intfd;charbuff;intcounter=0;if((fd=open(myfifo,O_RDONLY))0){printf(Functioncustomingerror\n);return-1;}printf(Enjoy:);lseek(fd,SEEK_SET,0);while(counterneed){while((read(fd,&buff,1)==1)&&(counterneed)){fputc(buff,stdout);/*-.就是在屏幕上/0的显示*/counter++;}}fputs(\n,stdout);close(fd);return0;}/*myfilecopy()函数:实现从sour_file文件的offset偏移处开始将count个字节数据复制到dest_file文件*/intmyfilecopy(constchar*sour_file,constchar*dest_file,intoffset,intcount,intcopy_mode){intin_file,out_file;intcounter=0;charbuff_unit;if((in_file=open(sour_file,O_RDONLY|O_NONBLOCK))0){printf(Functionmyfilecopyerrorinsourcefile\n);return-1;}if((out_file=open(dest_file,O_CREAT|O_RDWR|O_TRUNC|O_NONBLOCK,0644))0){printf(Functionmyfilecopyerrorindestinationfile:);return-1;}lseek(in_file,offset,SEEK_SET);while((read(in_file,&buff_unit,1)==1)&&(countercount)){write(out_file,&buff_unit,1);counter++;}close(in_file);close(out_file);return0;}/*custom()函数:实现FIFO消费者*/intcustom(intneed){intfd;/*对资源进行消费,need表示该消费的资源数目*/customing(fifo_file,need);if((fd=open(fifo_file,O_RDWR))0){printf(Functionmyfilecopyerrorinsource_file:);return-1;}/*为了模拟FIFO结构,对整个文件进平行行移动*/lock_set(fd,F_WRLCK);myfilecopy(fifo_file,tmp_file,need,MAX_FILE_SIZE,0);myfilecopy(tmp_file,fifo_file,0,MAX_FILE_SIZE,0);lock_set(fd,F_UNLCK);unlink(tmp_file);close(fd);return0;}intmain(intargc,char*argv[]){intcustomer_capacity=10;if(argc1)/*第一个参数指定需要消费的资源数目,默认值为10*/{sscanf(argv[1],%d,&customer_capacity);}if(customer_capacity0){custom(customer_capacity);}exit(EXIT_SUCCESS);}(3)分别编译生产者程序producer.c和消费者程序customer.c(4)确保编译没有错误后,先在控制台终端1上运行生产者程序:./producer120再在控制台终端2上运行消费者程序:./customer5五、实验数据及处理结果生产者程序:消费者程序:六、实验体会或对改进实验的
本文标题:实验四-文件操作
链接地址:https://www.777doc.com/doc-5709357 .html