IT培训机构|91免费精品视频|专注编程培训|91免费精品|软件开发培训_91免费国产视频_华清远见教育


實(shí)驗(yàn):linux文件讀/寫及上鎖

分享到:
           

    1.實(shí)驗(yàn)?zāi)康?/p>

    通過編寫文件讀寫及上鎖的程序,進(jìn)一步熟悉Linux中文件I/O相關(guān)的應(yīng)用開發(fā),并且熟練掌握open()、read()、write()、fcntl()等函數(shù)的使用。

    2.實(shí)驗(yàn)內(nèi)容

    在Linux中FIFO是一種進(jìn)程間的管道通信機(jī)制,Linux支持完整的FIFO通信機(jī)制。

    本實(shí)驗(yàn)內(nèi)容比較有趣,我們通過使用文件操作,仿真FIFO(先進(jìn)先出)結(jié)構(gòu)及生產(chǎn)者—消費(fèi)者運(yùn)行模型。

    本實(shí)驗(yàn)中需要打開兩個(gè)虛擬終端,分別運(yùn)行生產(chǎn)者程序(producer)和消費(fèi)者程序(customer),此時(shí)兩個(gè)進(jìn)程同時(shí)對(duì)同一個(gè)文件進(jìn)行讀寫操作。因?yàn)檫@個(gè)文件是臨界資源,所以可以使用文件鎖機(jī)制來保證兩個(gè)進(jìn)程對(duì)文件的訪問都是原子操作。

    先啟動(dòng)生產(chǎn)者進(jìn)程,它負(fù)責(zé)創(chuàng)建仿真FIFO結(jié)構(gòu)的文件(其實(shí)是一個(gè)普通文件)并投入生產(chǎn),就是按照給定的時(shí)間間隔,向FIFO文件寫入自動(dòng)生成的字符(在程序中用宏定義選擇使用數(shù)字還是使用英文字符),生產(chǎn)周期及要生產(chǎn)的資源數(shù)通過參數(shù)傳遞給進(jìn)程(默認(rèn)生產(chǎn)周期為1s,要生產(chǎn)的資源總數(shù)為10個(gè)字符,顯然默認(rèn)生產(chǎn)總時(shí)間為10s)。

    后啟動(dòng)的消費(fèi)者進(jìn)程按照給定的數(shù)目進(jìn)行消費(fèi),首先從文件中讀取相應(yīng)數(shù)目的字符并在屏幕上顯示,然后從文件中刪除剛才消費(fèi)過的數(shù)據(jù)。為了仿真FIFO結(jié)構(gòu),此時(shí)需要使用兩次復(fù)制來實(shí)現(xiàn)文件內(nèi)容的偏移。每次消費(fèi)的資源數(shù)通過參數(shù)傳遞給進(jìn)程,默認(rèn)值為10個(gè)字符。

    3.實(shí)驗(yàn)步驟

    (1)畫出實(shí)驗(yàn)流程圖。

    本實(shí)驗(yàn)的兩個(gè)程序的流程圖如圖2.5所示。


圖2.5 文件讀寫及上鎖實(shí)驗(yàn)流程圖

    (2)編寫代碼。

    本實(shí)驗(yàn)中的生產(chǎn)者程序的源代碼如下所示,其中用到的lock_set()函數(shù)可參見后面章節(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' /* 頭一個(gè)字符,可以用 'A' */
    #define COUNT_OF_ALPHABET 26 /* 字母字符的個(gè)數(shù) */

    #define DIGIT 2 /* 表示使用數(shù)字字符 */
    #define DIGIT_START '0' /* 頭一個(gè)字符 */
    #define COUNT_OF_DIGIT 10 /* 數(shù)字字符的個(gè)數(shù) */

    #define SIGN_TYPE ALPHABET /* 本實(shí)例選用英文字符 */
    const char *fifo_file = "./myfifo";/* 仿真FIFO文件名 */
    char buff[MAXLEN]; /* 緩沖區(qū) */

    /* 功能:生產(chǎn)一個(gè)字符并寫入到仿真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)
        {/* 第一個(gè)參數(shù)表示生產(chǎn)周期 */
            sscanf(argv[1], "%d", &time_step);
        }
        if (argc > 2)
        {/* 第二個(gè)參數(shù)表示需要生產(chǎn)的資源數(shù) */
            sscanf(argv[2], "%d", &time_life);
        }
        while (time_life--)
        {
            if (product() < 0)
            {
                break;
            }
            sleep(time_step);
        }

        exit(EXIT_SUCCESS);
    }

    本實(shí)驗(yàn)中的消費(fèi)者程序的源代碼如下所示:

    /* 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í)文件名 */

    /* 資源消費(fèi)函數(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); /* 消費(fèi)就是在屏幕上簡單的顯示 */
                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;
    }

    /* 功能:實(shí)現(xiàn)FIFO消費(fèi)者 */
    int custom(int need)
    {
        int fd;

        /* 對(duì)資源進(jìn)行消費(fèi),need表示該消費(fèi)的資源數(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),對(duì)整個(gè)文件內(nèi)容進(jìn)行平行移動(dòng) */
        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) /* 第一個(gè)參數(shù)指定需要消費(fèi)的資源數(shù)目,默認(rèn)值為10 */
        {
            sscanf(argv[1], "%d", &customer_capacity);
        }
        if (customer_capacity > 0)
        {
            custom(customer_capacity);
        }
        exit(EXIT_SUCCESS);
    }

    (3)先在宿主機(jī)上編譯該程序,如下所示:

    $ make clean; make

    (4)在確保沒有編譯錯(cuò)誤后,交叉編譯該程序,此時(shí)需要修改Makefile中的變量。

    CC = arm-linux-gcc /* 修改Makefile中的編譯器 */
    $ make clean; make

    (5)將生成的可執(zhí)行程序下載到目標(biāo)板上運(yùn)行。

    4.實(shí)驗(yàn)結(jié)果

    此實(shí)驗(yàn)在目標(biāo)板上的運(yùn)行結(jié)果如下所示。實(shí)驗(yàn)結(jié)果會(huì)和這兩個(gè)進(jìn)程運(yùn)行的具體過程相關(guān),希望讀者能具體分析每種情況,下面列出其中一種情況。

    終端一:

    $ ./producer 1 20 /* 生產(chǎn)周期為1s,需要生產(chǎn)的資源總數(shù)為20個(gè) */
    Write lock set by 21867
    Release lock by 21867
    Write lock set by 21867
    Release lock by 21867
    …

    終端二:

    $ ./customer 5 /* 需要消費(fèi)的資源數(shù)為5個(gè) */
    Enjoy:abcde /* 對(duì)資源進(jìn)行消費(fèi),即打印到屏幕上 */
    Write lock set by 21872 /* 為了仿真FIFO結(jié)構(gòu),進(jìn)行兩次復(fù)制 */
    Release lock by 21872

    在兩個(gè)進(jìn)程結(jié)束后,仿真FIFO文件的內(nèi)容如下:

    $ cat myfifo
    fghijklmnopqr /* a到e的5個(gè)字符已經(jīng)被消費(fèi),就剩下后面15個(gè)字符 */

    本文選自華清遠(yuǎn)見嵌入式培訓(xùn)教材《從實(shí)踐中學(xué)嵌入式Linux應(yīng)用程序開發(fā)》

   熱點(diǎn)鏈接:

   1、linux 文件鎖的實(shí)現(xiàn)及其應(yīng)用
   2、嵌入式Linux串口應(yīng)用編程之串口讀寫
   3、Linux文件系統(tǒng)之虛擬文件系統(tǒng)
   4、標(biāo)準(zhǔn)I/O操作函數(shù)詳解
   5、標(biāo)準(zhǔn)I/O操作的緩沖存儲(chǔ)類型

更多新聞>> 

主站蜘蛛池模板: 全功能护理训练模拟人-创伤护理人-高级电脑心肺复苏模型-上海康季 | 新乡市矿山起重机制造有限公司| 泰安兴润建材有限公司,泰安井盖定做,泰安警示桩定做,泰安雨水篦子定做,泰安操场篦子定做,泰安标志牌定做 | 离婚协议书怎么写_离婚协议书模板标准版_离婚协议书范本下载 - 离婚协议书 | 实验升降炉-箱式管式炉- 台车真空炉-熔块旋转炉-推板隧道窑-洛阳鲁威窑炉有限公司 | 延吉新闻网 - 未来之选·就是延吉 [YanJinews.com] | 硫酸、硫酸铵、氯磺酸、氯化亚砜、硫酸钾、对位酯生产销售 - 河北和合化工有限公司 | 上海协格机电科技股份有限公司-上海格力中央空调安装报价工程服务商 | 清河县隆鑫密封件有限公司,汽车用密封条,配电箱柜、集装箱密封胶条,建筑门窗、家具用密封条,无毒环保医用密封条,船舶、农机用密封条,异型产品 | 移动破碎机,欧版颚式破碎机-淄博巨鑫矿山机械有限公司 | 水暖毯厂家-水暖毯配件-河北鑫政扬家用电器有限公司 | 专注全球电机测试-电机测试系统-AIP艾普【官网】 | 河北高新技术企业认定,沧州商标注册,沧州9001质量管理体系认证,沧州高新技术企业认定,沧州体系认证,沧州商标续展,沧州版权登记,河北国瑞企业管理咨询有限公司 | 在线红外水分测控仪-SK-100水分测试仪-上海拓西电子科技有限公司 | 校园文化设计|文化墙建设|校园景观雕塑|校史馆设计-深圳市天合文化 | 中标通国际认证(深圳)有限公司-知识产权管理体系认证-湖北知识产权贯标 | 天空彩票天下彩,天空彩天空彩票免费资料,天空彩票与你同行开奖,天下彩正版资料大全 | 深圳物流公司_深圳物流_深圳物流专线-旺通达物流 | 找网页游戏鬼服 高返利鬼服游戏平台 鬼服开服表 - 猫游戏鬼服大全 | 企业资质认证-上海翼弘企业咨询管理有限公司 | 无锡心理咨询_江阴心理咨询_强迫症咨询_无锡笑一心理咨询有限公司 | 垃圾桶_垃圾桶厂家_临沂市旭宏塑料有限公司 | 南尔智能科技 南尔 小南管家 智慧中控屏 智能语音面板 - 深圳市南尔智能科技有限公司 | 山东正奇塑料机械有限公司,山东塑料机械,水带机组,塑料管材机,山东吹膜机组厂家,山东农膜机厂家 山东长青石油液压机械有限公司-致力于石油机械设备的研发制造,提供定制服务 | 疲劳试验机|电子万能试验机|摩擦磨损试验机|冲击试验机|济南全力测试技术有限公司 | 真空工业炉-真空油淬炉-真空气淬炉-高温石墨化炉-江苏华弘真空科技有限公司 | 山东汇河环保科技集团有限公司,水囊水袋,水罐,油囊,预压水袋,吊重水袋_山东汇河环保科技集团有限公司,水囊水袋,水罐,油囊,预压水袋,吊重水袋 | 西门子伺服电机维修_西门子变频器维修_西门子伺服驱动器维修_数控系统维修_PL维修-上海仰光电子 西克制冷官网│制冷机组冷风机冷库设备厂家-西克制冷(无锡)有限公司_西克制冷(无锡)有限公司 | 装修公司-吉诚装饰公司官网 | 手术示教系统-实训示教系统-数字化手术室-直播录播系统 - 深圳市视源视讯技术有限公司 | 江苏广分检测技术有限公司、电力安全工具检测、苏州绝缘工具检测、昆山电力安全工具检测-广分检测技术(苏州)有限公司 | 永磁变频空压机_青岛空压机_螺杆空压机_口罩专用空压机-青岛凯瑞特机电设备有限公司 | 徐州护栏,铝艺栏杆,铝艺大门,铝艺栏杆门,别墅铝艺大门-徐州桂丰金属科技有限公司 | 假肢价格-大腿假肢小腿假肢假手指-河南舒捷假肢厂家 | 佳龙食品集团|高端辣条领导品牌 加药装置-排油烟装置-工业滤水器-连云港灵动 | 液化气密度测定仪,原油有机氯测定仪-泰州市姜堰分析仪器厂 | 重庆消杀公司-重庆斗哥环保科技-灭鼠公司-重庆灭蟑螂-除四害-灭老鼠-灭虫-重庆灭白蚁公司 | 振动筛_直线振动筛_超声波振动筛-新乡市大汉振动机械有限公司 | 厦门鼎星五金制品有限公司-厦门弹簧,电池簧,扣簧 | 山东腾达源金属材料官网-耐磨板nm400,nm400耐磨钢板,nm500耐磨钢板切割,耐候板批发,高强板现货【价格】 | 全自动圆木多片锯_立式圆木多片锯价格_大型圆木多片锯厂家-邢台友创机械制造有限公司 |