資料介紹
6.6 實驗內(nèi)容
6.6.1 文件讀寫及上鎖
1.實驗?zāi)康?br /> 通過編寫文件讀寫及上鎖的程序,進一步熟悉Linux中文件I/O相關(guān)的應(yīng)用開發(fā),并且熟練掌握open()、read()、write()、fcntl()等函數(shù)的使用。
2.實驗內(nèi)容
在Linux中FIFO是一種進程之間的管道通信機制。Linux支持完整的FIFO通信機制。
本實驗內(nèi)容比較有趣,通過使用文件操作,仿真FIFO(先進先出)結(jié)構(gòu)以及生產(chǎn)者-消費者運行模型。
本實驗中需要打開兩個虛擬終端,分別運行生產(chǎn)者程序(producer)和消費者程序(customer)。此時兩個進程同時對同一個文件進行讀寫操作。因為這個文件是臨界資源,所以可以使用文件鎖機制來保證兩個進程對文件的訪問都是原子操作。
先啟動生產(chǎn)者進程,它負責(zé)創(chuàng)建仿真FIFO結(jié)構(gòu)的文件(其實是一個普通文件)并投入生產(chǎn),就是按照給定的時間間隔,向FIFO文件寫入自動生成的字符(在程序中用宏定義選擇使用數(shù)字還是使用英文字符),生產(chǎn)周期以及要生產(chǎn)的資源數(shù)通過參數(shù)傳遞給進程(默認生產(chǎn)周期為1s,要生產(chǎn)的資源數(shù)為10個字符)。
后啟動的消費者進程按照給定的數(shù)目進行消費,首先從文件中讀取相應(yīng)數(shù)目的字符并在屏幕上顯示,然后從文件中刪除剛才消費過的數(shù)據(jù)。為了仿真FIFO結(jié)構(gòu),此時需要使用兩次復(fù)制來實現(xiàn)文件內(nèi)容的偏移。每次消費的資源數(shù)通過參數(shù)傳遞給進程,默認值為10個字符。
3.實驗步驟
?。?)畫出實驗流程圖。
本實驗的兩個程序的流程圖如圖6.4所示。

圖6.4 節(jié)流程圖
(2)編寫代碼。
本實驗中的生產(chǎn)者程序的源代碼如下所示,其中用到的lock_set()函數(shù)可參見第6.3.2節(jié)。
/* producer.c */
#include 《stdio.h》
#include 《unistd.h》
#include 《stdlib.h》
#include 《string.h》
#include 《fcntl.h》
#include “mylock.h”
#define MAXLEN 10 /* 緩沖區(qū)大小最大值*/
#define ALPHABET 1 /* 表示使用英文字符 */
#define ALPHABET_START ‘a(chǎn)’ /* 頭一個字符,可以用 ‘A’*/
#define COUNT_OF_ALPHABET 26 /* 字母字符的個數(shù) */
#define DIGIT 2 /* 表示使用數(shù)字字符 */
#define DIGIT_START ‘0’ /* 頭一個字符 */
#define COUNT_OF_DIGIT 10 /* 數(shù)字字符的個數(shù) */
#define SIGN_TYPE ALPHABET /* 本實例選用英文字符 */
const char *fifo_file = “。/myfifo”; /* 仿真FIFO文件名 */
char buff[MAXLEN]; /* 緩沖區(qū) */
/* 功能:生產(chǎn)一個字符并寫入仿真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:/* 數(shù)字字符 */
{
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; /* 生產(chǎn)周期 */
int time_life = 10; /* 需要生產(chǎn)的資源數(shù) */
if (argc 》 1)
{/* 第一個參數(shù)表示生產(chǎn)周期 */
sscanf(argv[1], “%d”, &time_step);
}
if (argc 》 2)
{/* 第二個參數(shù)表示需要生產(chǎn)的資源數(shù) */
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”; /* 臨時文件名 */
/* 資源消費函數(shù) */
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個字節(jié)數(shù)據(jù)復(fù)制到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;
}
/* 功能:實現(xiàn)FIFO消費者 */
int custom(int need)
{
int fd;
/* 對資源進行消費,need表示該消費的資源數(shù)目 */
customing(fifo_file, need);
if ((fd = open(fifo_file, O_RDWR)) 《 0)
{
printf(“Function myfilecopy error in source_file:”);
return -1;
}
/* 為了模擬FIFO結(jié)構(gòu),對整個文件內(nèi)容進行平行移動 */
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) /* 第一個參數(shù)指定需要消費的資源數(shù)目,默認值為10 */
{
sscanf(argv[1], “%d”, &customer_capacity);
}
if (customer_capacity 》 0)
{
custom(customer_capacity);
}
exit(EXIT_SUCCESS);
}
?。?)先在宿主機上編譯該程序,如下所示:
$ make clean; make
?。?)在確保沒有編譯錯誤后,交叉編譯該程序,此時需要修改Makefile中的變量
CC = arm-linux-gcc /* 修改Makefile中的編譯器 */
$ make clean; make
?。?)將生成的可執(zhí)行程序下載到目標板上運行。
4.實驗結(jié)果
此實驗在目標板上的運行結(jié)果如下所示。實驗結(jié)果會和這兩個進程運行的具體過程相關(guān),希望讀者能具體分析每種情況。下面列出其中一種情況:
終端一:
$ 。/producer 1 20 /* 生產(chǎn)周期為1s,需要生產(chǎn)的資源數(shù)為20個 */
Write lock set by 21867
Release lock by 21867
Write lock set by 21867
Release lock by 21867
……
6.6.1 文件讀寫及上鎖
1.實驗?zāi)康?br /> 通過編寫文件讀寫及上鎖的程序,進一步熟悉Linux中文件I/O相關(guān)的應(yīng)用開發(fā),并且熟練掌握open()、read()、write()、fcntl()等函數(shù)的使用。
2.實驗內(nèi)容
在Linux中FIFO是一種進程之間的管道通信機制。Linux支持完整的FIFO通信機制。
本實驗內(nèi)容比較有趣,通過使用文件操作,仿真FIFO(先進先出)結(jié)構(gòu)以及生產(chǎn)者-消費者運行模型。
本實驗中需要打開兩個虛擬終端,分別運行生產(chǎn)者程序(producer)和消費者程序(customer)。此時兩個進程同時對同一個文件進行讀寫操作。因為這個文件是臨界資源,所以可以使用文件鎖機制來保證兩個進程對文件的訪問都是原子操作。
先啟動生產(chǎn)者進程,它負責(zé)創(chuàng)建仿真FIFO結(jié)構(gòu)的文件(其實是一個普通文件)并投入生產(chǎn),就是按照給定的時間間隔,向FIFO文件寫入自動生成的字符(在程序中用宏定義選擇使用數(shù)字還是使用英文字符),生產(chǎn)周期以及要生產(chǎn)的資源數(shù)通過參數(shù)傳遞給進程(默認生產(chǎn)周期為1s,要生產(chǎn)的資源數(shù)為10個字符)。
后啟動的消費者進程按照給定的數(shù)目進行消費,首先從文件中讀取相應(yīng)數(shù)目的字符并在屏幕上顯示,然后從文件中刪除剛才消費過的數(shù)據(jù)。為了仿真FIFO結(jié)構(gòu),此時需要使用兩次復(fù)制來實現(xiàn)文件內(nèi)容的偏移。每次消費的資源數(shù)通過參數(shù)傳遞給進程,默認值為10個字符。
3.實驗步驟
?。?)畫出實驗流程圖。
本實驗的兩個程序的流程圖如圖6.4所示。

圖6.4 節(jié)流程圖
(2)編寫代碼。
本實驗中的生產(chǎn)者程序的源代碼如下所示,其中用到的lock_set()函數(shù)可參見第6.3.2節(jié)。
/* producer.c */
#include 《stdio.h》
#include 《unistd.h》
#include 《stdlib.h》
#include 《string.h》
#include 《fcntl.h》
#include “mylock.h”
#define MAXLEN 10 /* 緩沖區(qū)大小最大值*/
#define ALPHABET 1 /* 表示使用英文字符 */
#define ALPHABET_START ‘a(chǎn)’ /* 頭一個字符,可以用 ‘A’*/
#define COUNT_OF_ALPHABET 26 /* 字母字符的個數(shù) */
#define DIGIT 2 /* 表示使用數(shù)字字符 */
#define DIGIT_START ‘0’ /* 頭一個字符 */
#define COUNT_OF_DIGIT 10 /* 數(shù)字字符的個數(shù) */
#define SIGN_TYPE ALPHABET /* 本實例選用英文字符 */
const char *fifo_file = “。/myfifo”; /* 仿真FIFO文件名 */
char buff[MAXLEN]; /* 緩沖區(qū) */
/* 功能:生產(chǎn)一個字符并寫入仿真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:/* 數(shù)字字符 */
{
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; /* 生產(chǎn)周期 */
int time_life = 10; /* 需要生產(chǎn)的資源數(shù) */
if (argc 》 1)
{/* 第一個參數(shù)表示生產(chǎn)周期 */
sscanf(argv[1], “%d”, &time_step);
}
if (argc 》 2)
{/* 第二個參數(shù)表示需要生產(chǎn)的資源數(shù) */
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”; /* 臨時文件名 */
/* 資源消費函數(shù) */
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個字節(jié)數(shù)據(jù)復(fù)制到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;
}
/* 功能:實現(xiàn)FIFO消費者 */
int custom(int need)
{
int fd;
/* 對資源進行消費,need表示該消費的資源數(shù)目 */
customing(fifo_file, need);
if ((fd = open(fifo_file, O_RDWR)) 《 0)
{
printf(“Function myfilecopy error in source_file:”);
return -1;
}
/* 為了模擬FIFO結(jié)構(gòu),對整個文件內(nèi)容進行平行移動 */
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) /* 第一個參數(shù)指定需要消費的資源數(shù)目,默認值為10 */
{
sscanf(argv[1], “%d”, &customer_capacity);
}
if (customer_capacity 》 0)
{
custom(customer_capacity);
}
exit(EXIT_SUCCESS);
}
?。?)先在宿主機上編譯該程序,如下所示:
$ make clean; make
?。?)在確保沒有編譯錯誤后,交叉編譯該程序,此時需要修改Makefile中的變量
CC = arm-linux-gcc /* 修改Makefile中的編譯器 */
$ make clean; make
?。?)將生成的可執(zhí)行程序下載到目標板上運行。
4.實驗結(jié)果
此實驗在目標板上的運行結(jié)果如下所示。實驗結(jié)果會和這兩個進程運行的具體過程相關(guān),希望讀者能具體分析每種情況。下面列出其中一種情況:
終端一:
$ 。/producer 1 20 /* 生產(chǎn)周期為1s,需要生產(chǎn)的資源數(shù)為20個 */
Write lock set by 21867
Release lock by 21867
Write lock set by 21867
Release lock by 21867
……
Linux
加入交流群
掃碼添加小助手
加入工程師交流群
下載該資料的人也在下載
下載該資料的人還在閱讀
更多 >
- STM32f103系列i2c讀寫文件at24c02 27次下載
- 字符串和文件I/O學(xué)習(xí)文檔下載 0次下載
- labview讀寫配置文件實例分享 49次下載
- 【嵌入式】文件操作
- C語言文件讀寫工程源代碼匯總下載 1次下載
- 使用單片機實現(xiàn)I2C總線的實驗文件免費下載 7次下載
- 單片機C51配套實驗例程之工業(yè)順序控制的程序和工程文件免費下載 23次下載
- MATLAB教程之經(jīng)典MATLAB文件操作的詳細資料說明 12次下載
- LabVIEW教程之字符串與文件IO的詳細資料說明 24次下載
- C語言教程之文件函數(shù)的詳細資料說明 1次下載
- Linux 系統(tǒng)應(yīng)用編程之標準I/O詳解 0次下載
- JAVA教程之復(fù)制文件 2次下載
- JAVA教程之壓縮中文文件名的文件 4次下載
- Delphi教程之Delphi中的ini文件的讀寫 12次下載
- JAVA教程之文件選擇器 12次下載
- PCA9554:8位I2C和SMBus I/O擴展器的深度解析 424次閱讀
- 如何實現(xiàn)Python復(fù)制文件操作 1.3k次閱讀
- PLC的I/O點數(shù)是什么意思 1.2w次閱讀
- Python利用pandas讀寫Excel文件 2.6k次閱讀
- 物理約束實踐:I/O約束 2.4k次閱讀
- 創(chuàng)建jar文件的過程 1.6k次閱讀
- 如何在Rust中讀寫文件 3k次閱讀
- OpenCV中YAML配置文件讀寫使用演示 1.7k次閱讀
- MATLAB文件讀寫和數(shù)據(jù)處理的詳細解釋 4k次閱讀
- FatFS文件系統(tǒng)在STM32F4上的移植和應(yīng)用 3.9k次閱讀
- 如何在STM32上實現(xiàn)USB主機讀寫U盤文件 1.8w次閱讀
- 使用EWPtool將源文件導(dǎo)入到IAR Embedded Workbench 4.4k次閱讀
- 編譯器將.c文件編譯為.o文件鏈接的過程 6.2k次閱讀
- Linux磁盤I/O的性能指標和查看性能工具 3.3k次閱讀
- CAM350如何導(dǎo)入gerber文件 2.1w次閱讀
下載排行
本周
- 1冷柜-電氣控制系統(tǒng)講解
- 13.68 MB | 4次下載 | 10 積分
- 2安川A1000變頻器中文版說明書
- 20.16 MB | 3次下載 | 3 積分
- 3直流電路的組成和基本定律
- 1.67 MB | 2次下載 | 免費
- 4丹佛斯2800系列變頻器說明書
- 8.00 MB | 1次下載 | 5 積分
- 5PC8011同步開關(guān)型降壓3.5A單節(jié)鋰電池充電管理電路技術(shù)手冊
- 0.74 MB | 1次下載 | 免費
- 6ES7243E+ES8311音頻錄制與播放電路資料
- 0.06 MB | 1次下載 | 5 積分
- 7SDM02 激光測距模塊產(chǎn)品手冊
- 0.43 MB | 1次下載 | 免費
- 8SDFM 激光測距模塊模組手冊
- 0.54 MB | 1次下載 | 免費
本月
- 1CH341編程器軟件NeoProgrammer_2.2.0.10
- 20.47 MB | 170次下載 | 1 積分
- 22025智能家居傳感器市場分析及創(chuàng)新應(yīng)用
- 3.11 MB | 43次下載 | 免費
- 3RV1126B系列開發(fā)板產(chǎn)品資料
- 4.19 MB | 18次下載 | 免費
- 4CH341編程軟件下載
- 2.50 MB | 16次下載 | 5 積分
- 5全志系列-米爾基于T153核心板開發(fā)板 四核異構(gòu)、3路千兆網(wǎng),賦能多元化工業(yè)場景
- 3.05 MB | 12次下載 | 免費
- 6【開源】60余套STM32單片機、嵌入式Linux、物聯(lián)網(wǎng)、人工智能項目案例及入門學(xué)習(xí)資源包
- 10.55 MB | 8次下載 | 免費
- 7冷柜-電氣控制系統(tǒng)講解
- 13.68 MB | 4次下載 | 10 積分
- 8特斯拉MODEL S車載充電機主電路回路原理圖
- 0.81 MB | 4次下載 | 3 積分
總榜
- 1matlab軟件下載入口
- 未知 | 935137次下載 | 10 積分
- 2開源硬件-PMP21529.1-4 開關(guān)降壓/升壓雙向直流/直流轉(zhuǎn)換器 PCB layout 設(shè)計
- 1.48MB | 420064次下載 | 10 積分
- 3Altium DXP2002下載入口
- 未知 | 233094次下載 | 10 積分
- 4電路仿真軟件multisim 10.0免費下載
- 340992 | 191448次下載 | 10 積分
- 5十天學(xué)會AVR單片機與C語言視頻教程 下載
- 158M | 183356次下載 | 10 積分
- 6labview8.5下載
- 未知 | 81604次下載 | 10 積分
- 7Keil工具MDK-Arm免費下載
- 0.02 MB | 73824次下載 | 10 積分
- 8LabVIEW 8.6下載
- 未知 | 65991次下載 | 10 積分
電子發(fā)燒友App





創(chuàng)作
發(fā)文章
發(fā)帖
提問
發(fā)資料
發(fā)視頻
上傳資料賺積分
評論