资料介绍
6.6 实验内容
6.6.1 文件读写及上锁
1.实验目的
通过编写文件读写及上锁的程序,进一步熟悉Linux中文件I/O相关的应用开发,并且熟练掌握open()、read()、write()、fcntl()等函数的使用。
2.实验内容
在Linux中FIFO是一种进程之间的管道通信机制。Linux支持完整的FIFO通信机制。
本实验内容比较有趣,通过使用文件操作,仿真FIFO(先进先出)结构以及生产者-消费者运行模型。
本实验中需要打开两个虚拟终端,分别运行生产者程序(producer)和消费者程序(customer)。此时两个进程同时对同一个文件进行读写操作。因为这个文件是临界资源,所以可以使用文件锁机制来保证两个进程对文件的访问都是原子操作。
先启动生产者进程,它负责创建仿真FIFO结构的文件(其实是一个普通文件)并投入生产,就是按照给定的时间间隔,向FIFO文件写入自动生成的字符(在程序中用宏定义选择使用数字还是使用英文字符),生产周期以及要生产的资源数通过参数传递给进程(默认生产周期为1s,要生产的资源数为10个字符)。
后启动的消费者进程按照给定的数目进行消费,首先从文件中读取相应数目的字符并在屏幕上显示,然后从文件中删除刚才消费过的数据。为了仿真FIFO结构,此时需要使用两次复制来实现文件内容的偏移。每次消费的资源数通过参数传递给进程,默认值为10个字符。
3.实验步骤
(1)画出实验流程图。
本实验的两个程序的流程图如图6.4所示。
图6.4 节流程图
(2)编写代码。
本实验中的生产者程序的源代码如下所示,其中用到的lock_set()函数可参见第6.3.2节。
/* producer.c */
#include 《stdio.h》
#include 《unistd.h》
#include 《stdlib.h》
#include 《string.h》
#include 《fcntl.h》
#include “mylock.h”
#define MAXLEN 10 /* 缓冲区大小最大值*/
#define ALPHABET 1 /* 表示使用英文字符 */
#define ALPHABET_START ‘a’ /* 头一个字符,可以用 ‘A’*/
#define COUNT_OF_ALPHABET 26 /* 字母字符的个数 */
#define DIGIT 2 /* 表示使用数字字符 */
#define DIGIT_START ‘0’ /* 头一个字符 */
#define COUNT_OF_DIGIT 10 /* 数字字符的个数 */
#define SIGN_TYPE ALPHABET /* 本实例选用英文字符 */
const char *fifo_file = “。/myfifo”; /* 仿真FIFO文件名 */
char buff[MAXLEN]; /* 缓冲区 */
/* 功能:生产一个字符并写入仿真FIFO文件中 */
int product(void)
{
int fd;
unsigned int sign_type, sign_start, sign_count, size;
static unsigned int counter = 0;
/* 打开仿真FIFO文件 */
if ((fd = open(fifo_file, O_CREAT|O_RDWR|O_APPEND, 0644)) 《 0)
{
printf(“Open fifo file error\n”);
exit(1);
}
sign_type = SIGN_TYPE;
switch(sign_type)
{
case ALPHABET:/* 英文字符 */
{
sign_start = ALPHABET_START;
sign_count = COUNT_OF_ALPHABET;
}
break;
case DIGIT:/* 数字字符 */
{
sign_start = DIGIT_START;
sign_count = COUNT_OF_DIGIT;
}
break;
default:
{
return -1;
}
}/*end of switch*/
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: write error\n”);
return -1;
}
lock_set(fd, F_UNLCK); /* 解锁 */
close(fd);
return 0;
}
int main(int argc ,char *argv[])
{
int time_step = 1; /* 生产周期 */
int time_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 */
#include 《stdio.h》
#include 《unistd.h》
#include 《stdlib.h》
#include 《fcntl.h》
#define MAX_FILE_SIZE 100 * 1024 * 1024 /* 100M*/
const char *fifo_file = “。/myfifo”; /* 仿真FIFO文件名 */
const char *tmp_file = “。/tmp”; /* 临时文件名 */
/* 资源消费函数 */
int customing(const char *myfifo, int need)
{
int fd;
char buff;
int counter = 0;
if ((fd = open(myfifo, O_RDONLY)) 《 0)
{
printf(“Function customing error\n”);
return -1;
}
printf(“Enjoy:”);
lseek(fd, SEEK_SET, 0);
while (counter 《 need)
{
while ((read(fd, &buff, 1) == 1) && (counter 《 need))
{
fputc(buff, stdout); /* 消费就是在屏幕上简单的显示 */
counter++;
}
fputs(“\n”, stdout);
close(fd);
return 0;
}
/* 功能:从sour_file文件的offset偏移处开始
将count个字节数据复制到dest_file文件 */
int myfilecopy(const char *sour_file,
const char *dest_file, int offset, int count, int copy_mode)
{
int in_file, out_file;
int counter = 0;
char buff_unit;
if ((in_file = open(sour_file, O_RDONLY|O_NONBLOCK)) 《 0)
{
printf(“Function myfilecopy error in source file\n”);
return -1;
}
if ((out_file = open(dest_file,
O_CREAT|O_RDWR|O_TRUNC|O_NONBLOCK, 0644)) 《 0)
{
printf(“Function myfilecopy error in destination file:”);
return -1;
}
lseek(in_file, offset, SEEK_SET);
while ((read(in_file, &buff_unit, 1) == 1) && (counter 《 count))
{
write(out_file, &buff_unit, 1);
counter++;
}
close(in_file);
close(out_file);
return 0;
}
/* 功能:实现FIFO消费者 */
int custom(int need)
{
int fd;
/* 对资源进行消费,need表示该消费的资源数目 */
customing(fifo_file, need);
if ((fd = open(fifo_file, O_RDWR)) 《 0)
{
printf(“Function myfilecopy error in source_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);
return 0;
}
int main(int argc ,char *argv[])
{
int customer_capacity = 10;
if (argc 》 1) /* 第一个参数指定需要消费的资源数目,默认值为10 */
{
sscanf(argv[1], “%d”, &customer_capacity);
}
if (customer_capacity 》 0)
{
custom(customer_capacity);
}
exit(EXIT_SUCCESS);
}
(3)先在宿主机上编译该程序,如下所示:
$ make clean; make
(4)在确保没有编译错误后,交叉编译该程序,此时需要修改Makefile中的变量
CC = arm-linux-gcc /* 修改Makefile中的编译器 */
$ make clean; make
(5)将生成的可执行程序下载到目标板上运行。
4.实验结果
此实验在目标板上的运行结果如下所示。实验结果会和这两个进程运行的具体过程相关,希望读者能具体分析每种情况。下面列出其中一种情况:
终端一:
$ 。/producer 1 20 /* 生产周期为1s,需要生产的资源数为20个 */
Write lock set by 21867
Release lock by 21867
Write lock set by 21867
Release lock by 21867
……
6.6.1 文件读写及上锁
1.实验目的
通过编写文件读写及上锁的程序,进一步熟悉Linux中文件I/O相关的应用开发,并且熟练掌握open()、read()、write()、fcntl()等函数的使用。
2.实验内容
在Linux中FIFO是一种进程之间的管道通信机制。Linux支持完整的FIFO通信机制。
本实验内容比较有趣,通过使用文件操作,仿真FIFO(先进先出)结构以及生产者-消费者运行模型。
本实验中需要打开两个虚拟终端,分别运行生产者程序(producer)和消费者程序(customer)。此时两个进程同时对同一个文件进行读写操作。因为这个文件是临界资源,所以可以使用文件锁机制来保证两个进程对文件的访问都是原子操作。
先启动生产者进程,它负责创建仿真FIFO结构的文件(其实是一个普通文件)并投入生产,就是按照给定的时间间隔,向FIFO文件写入自动生成的字符(在程序中用宏定义选择使用数字还是使用英文字符),生产周期以及要生产的资源数通过参数传递给进程(默认生产周期为1s,要生产的资源数为10个字符)。
后启动的消费者进程按照给定的数目进行消费,首先从文件中读取相应数目的字符并在屏幕上显示,然后从文件中删除刚才消费过的数据。为了仿真FIFO结构,此时需要使用两次复制来实现文件内容的偏移。每次消费的资源数通过参数传递给进程,默认值为10个字符。
3.实验步骤
(1)画出实验流程图。
本实验的两个程序的流程图如图6.4所示。
图6.4 节流程图
(2)编写代码。
本实验中的生产者程序的源代码如下所示,其中用到的lock_set()函数可参见第6.3.2节。
/* producer.c */
#include 《stdio.h》
#include 《unistd.h》
#include 《stdlib.h》
#include 《string.h》
#include 《fcntl.h》
#include “mylock.h”
#define MAXLEN 10 /* 缓冲区大小最大值*/
#define ALPHABET 1 /* 表示使用英文字符 */
#define ALPHABET_START ‘a’ /* 头一个字符,可以用 ‘A’*/
#define COUNT_OF_ALPHABET 26 /* 字母字符的个数 */
#define DIGIT 2 /* 表示使用数字字符 */
#define DIGIT_START ‘0’ /* 头一个字符 */
#define COUNT_OF_DIGIT 10 /* 数字字符的个数 */
#define SIGN_TYPE ALPHABET /* 本实例选用英文字符 */
const char *fifo_file = “。/myfifo”; /* 仿真FIFO文件名 */
char buff[MAXLEN]; /* 缓冲区 */
/* 功能:生产一个字符并写入仿真FIFO文件中 */
int product(void)
{
int fd;
unsigned int sign_type, sign_start, sign_count, size;
static unsigned int counter = 0;
/* 打开仿真FIFO文件 */
if ((fd = open(fifo_file, O_CREAT|O_RDWR|O_APPEND, 0644)) 《 0)
{
printf(“Open fifo file error\n”);
exit(1);
}
sign_type = SIGN_TYPE;
switch(sign_type)
{
case ALPHABET:/* 英文字符 */
{
sign_start = ALPHABET_START;
sign_count = COUNT_OF_ALPHABET;
}
break;
case DIGIT:/* 数字字符 */
{
sign_start = DIGIT_START;
sign_count = COUNT_OF_DIGIT;
}
break;
default:
{
return -1;
}
}/*end of switch*/
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: write error\n”);
return -1;
}
lock_set(fd, F_UNLCK); /* 解锁 */
close(fd);
return 0;
}
int main(int argc ,char *argv[])
{
int time_step = 1; /* 生产周期 */
int time_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 */
#include 《stdio.h》
#include 《unistd.h》
#include 《stdlib.h》
#include 《fcntl.h》
#define MAX_FILE_SIZE 100 * 1024 * 1024 /* 100M*/
const char *fifo_file = “。/myfifo”; /* 仿真FIFO文件名 */
const char *tmp_file = “。/tmp”; /* 临时文件名 */
/* 资源消费函数 */
int customing(const char *myfifo, int need)
{
int fd;
char buff;
int counter = 0;
if ((fd = open(myfifo, O_RDONLY)) 《 0)
{
printf(“Function customing error\n”);
return -1;
}
printf(“Enjoy:”);
lseek(fd, SEEK_SET, 0);
while (counter 《 need)
{
while ((read(fd, &buff, 1) == 1) && (counter 《 need))
{
fputc(buff, stdout); /* 消费就是在屏幕上简单的显示 */
counter++;
}
fputs(“\n”, stdout);
close(fd);
return 0;
}
/* 功能:从sour_file文件的offset偏移处开始
将count个字节数据复制到dest_file文件 */
int myfilecopy(const char *sour_file,
const char *dest_file, int offset, int count, int copy_mode)
{
int in_file, out_file;
int counter = 0;
char buff_unit;
if ((in_file = open(sour_file, O_RDONLY|O_NONBLOCK)) 《 0)
{
printf(“Function myfilecopy error in source file\n”);
return -1;
}
if ((out_file = open(dest_file,
O_CREAT|O_RDWR|O_TRUNC|O_NONBLOCK, 0644)) 《 0)
{
printf(“Function myfilecopy error in destination file:”);
return -1;
}
lseek(in_file, offset, SEEK_SET);
while ((read(in_file, &buff_unit, 1) == 1) && (counter 《 count))
{
write(out_file, &buff_unit, 1);
counter++;
}
close(in_file);
close(out_file);
return 0;
}
/* 功能:实现FIFO消费者 */
int custom(int need)
{
int fd;
/* 对资源进行消费,need表示该消费的资源数目 */
customing(fifo_file, need);
if ((fd = open(fifo_file, O_RDWR)) 《 0)
{
printf(“Function myfilecopy error in source_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);
return 0;
}
int main(int argc ,char *argv[])
{
int customer_capacity = 10;
if (argc 》 1) /* 第一个参数指定需要消费的资源数目,默认值为10 */
{
sscanf(argv[1], “%d”, &customer_capacity);
}
if (customer_capacity 》 0)
{
custom(customer_capacity);
}
exit(EXIT_SUCCESS);
}
(3)先在宿主机上编译该程序,如下所示:
$ make clean; make
(4)在确保没有编译错误后,交叉编译该程序,此时需要修改Makefile中的变量
CC = arm-linux-gcc /* 修改Makefile中的编译器 */
$ make clean; make
(5)将生成的可执行程序下载到目标板上运行。
4.实验结果
此实验在目标板上的运行结果如下所示。实验结果会和这两个进程运行的具体过程相关,希望读者能具体分析每种情况。下面列出其中一种情况:
终端一:
$ 。/producer 1 20 /* 生产周期为1s,需要生产的资源数为20个 */
Write lock set by 21867
Release lock by 21867
Write lock set by 21867
Release lock by 21867
……
下载该资料的人也在下载
下载该资料的人还在阅读
更多 >
- STM32f103系列i2c读写文件at24c02 22次下载
- 字符串和文件I/O学习文档下载 0次下载
- labview读写配置文件实例分享 45次下载
- 【嵌入式】文件操作
- C语言文件读写工程源代码汇总下载 1次下载
- 使用单片机实现I2C总线的实验文件免费下载 7次下载
- 单片机C51配套实验例程之工业顺序控制的程序和工程文件免费下载 21次下载
- MATLAB教程之经典MATLAB文件操作的详细资料说明 11次下载
- LabVIEW教程之字符串与文件IO的详细资料说明 24次下载
- C语言教程之文件函数的详细资料说明 1次下载
- Linux 系统应用编程之标准I/O详解 0次下载
- C#教程之文件加密 17次下载
- JAVA教程之复制文件 2次下载
- JAVA教程之压缩中文文件名的文件 4次下载
- Delphi教程之Delphi中的ini文件的读写 11次下载
- 如何实现Python复制文件操作 246次阅读
- PLC的I/O点数是什么意思 1581次阅读
- Python利用pandas读写Excel文件 988次阅读
- 物理约束实践:I/O约束 877次阅读
- 创建jar文件的过程 708次阅读
- 如何在Rust中读写文件 1749次阅读
- OpenCV中YAML配置文件读写使用演示 664次阅读
- MATLAB文件读写和数据处理的详细解释 2566次阅读
- FatFS文件系统在STM32F4上的移植和应用 2245次阅读
- 如何在STM32上实现USB主机读写U盘文件 1.2w次阅读
- 使用EWPtool将源文件导入到IAR Embedded Workbench 1940次阅读
- 编译器将.c文件编译为.o文件链接的过程 4270次阅读
- Linux磁盘I/O的性能指标和查看性能工具 2459次阅读
- CAM350如何导入gerber文件 1.9w次阅读
- 沁恒股份U盘和SD卡文件管理控制芯片CH376简介 2892次阅读
下载排行
本周
- 1TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 2开关电源基础知识
- 5.73 MB | 6次下载 | 免费
- 3100W短波放大电路图
- 0.05 MB | 4次下载 | 3 积分
- 4嵌入式linux-聊天程序设计
- 0.60 MB | 3次下载 | 免费
- 5基于FPGA的光纤通信系统的设计与实现
- 0.61 MB | 2次下载 | 免费
- 6基于FPGA的C8051F单片机开发板设计
- 0.70 MB | 2次下载 | 免费
- 751单片机窗帘控制器仿真程序
- 1.93 MB | 2次下载 | 免费
- 8基于51单片机的RGB调色灯程序仿真
- 0.86 MB | 2次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33564次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21548次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6653次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537796次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420026次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191185次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183278次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论
查看更多