Linux实验报告.docx
- 文档编号:10765982
- 上传时间:2023-02-22
- 格式:DOCX
- 页数:97
- 大小:420.11KB
Linux实验报告.docx
《Linux实验报告.docx》由会员分享,可在线阅读,更多相关《Linux实验报告.docx(97页珍藏版)》请在冰豆网上搜索。
Linux实验报告
南昌大学实验报告
学生姓名:
王维学号:
6100212202专业班级:
网工121班
实验类型:
□验证□综合□设计□创新实验日期:
实验成绩:
一、实验项目名称
实验4:
文件操作
二、实验目的
通过编写文件读写及上锁的程序,进一步熟悉Linux中文件I/O相关的应用开发,并并且熟练掌握open()、read()、write()、fcntl()等函数的使用。
三、实验内容
在Linux中FIFO是一种进程之间的管道通信机制。
Linux支持完整的FIFO通信机制。
本实验内容,通过使用文件操作,仿真FIFO(先进先出)结构以及生产者-消费者运行模型。
本实验中需要打开两个虚拟终端,分别运行生产者程序(producer)和消费者程序(customer)。
此时两个进程同时对同一个文件进行读写操作。
因为这个文件是临界资源,所以可以使用文件锁机制来保证两个进程对文件的访问都是原子操作。
先启动生产者进程,它负责创建仿真FIFO结构的文件(其实是一个普通文件)并投入生产,就是按照给定的时间间隔,向FIFO文件写入自动生成的字符(在程序中用宏定义选择使用数字还是使用英文字符),生产周期以及要生产的资源数通过参数传递给进程(默认生产周期为1s,要生产的资源数为10个字符)。
后启动的消费者进程按照给定的数目进行消费,首先从文件中读取相应数目的字符并在屏幕上显示,然后从文件中删除刚才消费过的数据。
为了仿真FIFO结构,此时需要使用两次复制来实现文件内容的偏移。
每次消费的资源数通过参数传递给进程,默认值为10个字符。
四、实验步骤
(1)实验流程图
本实验的两个程序的流程图如图:
开始开始
(producer)(customer)
消费资源
创建FIFO结构文件(打印字符)
否
消费够了吗?
生产一个资源
是
上锁
上锁
将剩下的数据拷贝到
等待临时文件tmp中
一秒将“生产”的字符
写入到FIFO结构文件
用临时文件tmp覆盖
原数据文件,这样
模拟FIFO结构
解锁
解锁
生产完了吗?
删除临时文件
结束结束
图6.4节流程图
(2)代码
头部文件代码:
mylock.h
structmyflock{
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*/#include
#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文件中*/
intproduct(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(argc>1){/*第一个参数表示生产周期*/sscanf(argv[1],"%d",&time_step);}if(argc>2){/*第二个参数表示需要生产的资源数*/sscanf(argv[2],"%d",&time_life);}while(time_life--){if(product()<0){break;}sleep(time_step);}exit(EXIT_SUCCESS);}
消费者程序的源代码:
customer.c
/*customer.c*/
#include
#include
#include"mylock.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(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)&&(counter /*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(argc>1)/*第一个参数指定需要消费的资源数目,默认值为10*/{sscanf(argv[1],"%d",&customer_capacity);}if(customer_capacity>0){custom(customer_capacity);}exit(EXIT_SUCCESS);} (3)分别编译生产者程序producer.c和消费者程序customer.c (4)确保编译没有错误后,先在控制台终端1上运行生产者程序: ./producer120 再在控制台终端2上运行消费者程序: ./customer5 五、 实验结果 生产者的输出信息重复了20次,上面只截图一部分。 下面是消费者的运行结果 六、附加实验 用write,read,open等系统调用编写分别实现如下功能的程序(要求进行必要的出错检查): (1)创建一个文件testfile.txt,文件内容从键盘输入; (2)将testfile.txt的内容显示在屏幕上,并将testfile.txt的内容复制到一个新的文件file2.txt中。 附加实验源码: /*test.c*/ #include #include #include #include #include #include #defineMAXSIZE128 constchar*file1="testfile.txt"; constchar*file2="file2.txt"; intmain(intargc,char**argv) { intfd,fd2; if((fd=open(file1,O_CREAT|O_RDWR|O_TRUNC,0644))==-1) { if(errno! =EEXIST) { perror("openfailed\n"); exit(EXIT_FAILURE); } } if((fd2=open(file2,O_CREAT|O_WRONLY|O_TRUNC,0644))==-1) { if(errno! =EEXIST) { perror("openfailed\n"); exit(EXIT_FAILURE); } } intsize; charbuf[MAXSIZE]; if(fgets(buf,MAXSIZE,stdin)==NULL) { perror("fgetsfailed\n"); exit(EXIT_FAILURE); } if(write(fd,buf,strlen(buf))<0) { perror("写入fd失败\n"); exit(EXIT_FAILURE); } lseek(fd,0,SEEK_SET); printf("开始拷贝%s到%s中...\n",file1,file2); while((size=read(fd,buf,strlen(buf)))==MAXSIZE) { if(write(fd2,buf,size)<0) { perror("写入fd2失败\n"); exit(EXIT_FAILURE); } } printf("拷贝了%d个字符\n",size); if(size<0) { perror("readfailed\n"); exit(EXIT_FAILURE); } elseif(write(fd2,buf,strlen(buf))<0) { perror("readfailed\n"); exit(EXIT_FAILURE); } printf("拷贝完成\n"); } 实验结果: 七、实验总结 通过本次实验,学会了Linux环境下的文件的基本IO操作。 首先要使用open函数获得一个文件描述符fd,可以给open函数指定一些文件打开的参数,比如权限,模式等等。 然后对于文件的所有操作其实都是针对文件描述符的操作,使用read,和write函数来可进行读写操作。 系统默认有三个文件描述符: 0(标准输入)、1(标准输出)、2(标准输出)。 可以看作是普通文件,来对其进行读写操作。 另外测试代码中,存在错误。 比如lseek函数,测试代码中是: lseek(fd,SEEK_SET,0);实际应该写作lseek(fd,0,SEEK_SET);也就是说把第二个参数和第三个参数的顺序搞反了,虽然错误代码也能运行通过,这只不过是因为SEEK_SET是一个宏,而它恰好等于0罢了。 另外本实验在运行成功之后,我多此一举地使用gcc–O2重新编译了一次,结果优化后的代码运行的时候出现了一些问题,好像是文件锁没有及时解除,一直提示已经加锁。 这告诉我,不是所有代码都时候优化,否则可能会出现问题。 不加-O2直接编译是完全没问题的。 南昌大学实验报告 学生姓名: 王维学号: 6100212202专业班级: 网工121班 实验类型: □验证□综合□设计□创新实验日期: 实验成绩: 一、实验项目名称 实验5: 多路复用式串口操作 二、实验项目名称 通过编写多路复用式串口读写,进一步理解多路复用函数的用法,同时更加熟练掌握Linux设备文件的读写方法。 三、实验内容 本实验主要实现两台机器(宿主机和目标机)之间的串口通信,每台机器都可以发送和接收数据。 除了串口设备名称不同(宿主机上使用串口1: /dev/ttyS1,而在目标机上使用串口2: /dev/ttyS2),两台机器上的程序基本相同。 四、实验步骤 (1)流程图两台机器上的程序使用同样的流程图。 (2)编写代码 /*uart_api.h*/ #ifndefUART_API_H #defineUART_API_H #defineGNR_COM0 #defineUSB_COM1 #defineCOM_TYPEGNR_COM #defineMAX_COM_NUM3 #defineHOST_COM_PORT1 #defineTARGET_COM_PORT2 #defineBUFFER_SIZE1024 #defineTIME_DELAY180 #defineSEL_FILE_NUM2 #defineRECV_FILE_NAME"recv.dat" intopen_port(intcom_port); intset_com_config(intfd,intbaud_rate,intdata_bits,charparity,intstop_bits); #endif/*UART_API_H*/ /*uart_api.c*/ #include #include #include #include #include #include #include #include"uart_api.h" /*打开串口函数*/ intopen_port(intcom_port) { intfd; #if(COM_TYPE==GNR_COM) char*dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"}; #else char*dev[]={"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2"}; #endif if((com_port<0)||(com_port>MAX_COM_NUM)) { return-1; } fd=open(dev[com_port-1],O_RDWR|O_NOCTTY|O_NDELAY); if(fd<0) { perror("openserialport"); return(-1); } /*恢复串口为阻塞状态*/ if(fcntl(fd,F_SETFL,0)<0) { perror("fcntlF_SETFL\n"); } /*测试是否为终端设备*/ if(isatty(STDIN_FILENO)==0) { perror("standardinputisnotaterminaldevice"); } returnfd; } intset_com_config(intfd,intbaud_rate,intdata_bits,charparity
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux实 Linux