Linux 基本语句_9_C语言_生产者消费者

news2024/11/20 11:52:06

完整版生产者代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h> 
#include <string.h>

#define MAXLEN 10
#define ALPHABET 1
#define ALPHABET_START '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 = "./FIFO.txt";

char buf[MAXLEN];

int lock_set(int fd, int type){
	struct flock old_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("Read lock already set by %d\n", lock.l_pid);
	   }
	   else if(lock.l_type == F_WRLCK){
	   	printf("Write lock already set by %d\n", lock.l_pid);
	   } 
	} 
	
	/*上述可能由于不是解锁状态l_type被设置成了相应的锁值下方进行上锁操作时要再次调用type*/ 
	lock.l_type = type;
	
	if((fcntl(fd, F_SETLKW, &lock)) < 0){//上锁失败 
		printf("Lock failed:type  = %d\n", lock.l_type);
		return -1;
	}
	
	switch(lock.l_type){
		case F_RDLCK:
			printf("Read lock set by %d\n", getpid());//获取当前进程的ID
			break;
		case F_WRLCK:
		    printf("Write lock set by %d\n", getpid());
	        break;
		case F_UNLCK:
		    printf("Release lock by %d\n", getpid());//解锁返回1 
			return 1;
			break; 
	}
	
	return 0;//上锁返回0 
}

int product(void){
	int fd;
	unsigned int sign_type, sign_start, sign_count, size;
	static unsigned int counter = 0;//只会执行一次 
	if((fd = open(fifo_file, O_WRONLY|O_APPEND)) < 0){//只写方式打开 ,追加模式 
	   perror("open error");
	   return -1;
    }
    sign_type = SIGN_TYPE;//英文字符集合 
    
    switch(sign_type){
    	case ALPHABET:
		     sign_start = ALPHABEF_START;
			 sign_count = COUNT_OF_ALPHABET;//26
			 break;
		case DIGIT:
		    sign_start = DIGIT_START;
			sign_count = COUNT_OF_DIGIT;
			break;
		default:
		    return -1; 
	}
	
	sprintf(buf, "%c", (sign_start + counter));//将字符写入buf缓冲区
	counter = (counter + 1) % sign_count;
	
	lock_set(fd, F_WRLCK);//写锁
	
	if((size = write(fd, buf, strlen(buf))) < 0){//打开失败,否者写入 
		perror("producer:write error");
		return -1; 
	}
	lock_set(fd, F_UNLCK);//解锁
	
	close(fd);
	return 0; 
}

int main(int argc, const char * argv[]){
	int time_step = 1;//周期 
	int time_life = 10;//生产数量
	
	close(open(fifo_file, O_REONLY|O_CREAT|O_TRUNC, 0664));//创建文件 
	
	if(argc > 1){
		sscanf(argv[1], "%d", &time_step);//将argv[1]转成整数存入time_step中 
	}
	
	if(argc > 2){
		sscanf(argv[2], "%d", &time_life);
	} 
	
	while(time_life --){
		if(product() < 0){
			break;
		} 
		sleep(time_step);
	}
	return 0;
}

流程:
在这里插入图片描述

原版代码有点缺失和问题,添加的代码如下:

原版代码缺少创建文件函数,以及没有对文件清空的函数
每次启动一轮生产,为了方便观察将文件上次生产的内容清空:

close(open(fifo_file, O_REONLY|O_CREAT|O_TRUNC, 0664));//创建文件&清空

文件打开模式必须是追加模式,否则生产的新数据会覆盖原有数据:

if((fd = open(fifo_file, O_WRONLY|O_APPEND)) < 0)

运行效果:

FIFO.txt文件上次运行时残留有数据
在这里插入图片描述

生产五个数据:
在这里插入图片描述
文件之前生产信息被清除,取而代之的是新数据:

在这里插入图片描述

完整版消费者代码:

 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/file.h> 
 #include <string.h>
 
 #define MAX_FILE_SIZE 100 * 1024 * 102
 
 
 const char *fifo_file  = "./FIFO.txt";
                                       
 const char *temp_file = "./temp";
 

int lock_set(int fd, int type){
        struct flock old_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("Read lock already set by %d\n", lock.l_pid);
              }
             else if(lock.l_type == F_WRLCK){
                 printf("Write lock already set by %d\n", lock.l_pid);
            }
      }                     
     /*上述可能由于不是解锁状态l_type被设置成了相应的锁值下方进行上锁操作时要再次调用type*/ 
    lock.l_type = type;                                         
    if((fcntl(fd, F_SETLKW, &lock)) < 0){//上锁失败             
       printf("Lock failed:type  = %d\n", lock.l_type);
       return -1;
    }
     
    switch(lock.l_type){
        case F_RDLCK:
                    printf("Read lock set by %d\n", getpid());//获取当前进程的ID
                    break;                                                                     
        case F_WRLCK:
                    printf("Write lock set by %d\n", getpid());
                    break;
        case F_UNLCK:
                    printf("Release lock by %d\n", getpid());//解锁返回1 
                    return 1;
                    break;
    }
    return 0;//上锁返回0 
}

int customing(const char * myfifo, int need){
        int fd;
        char buf;
        int counter = 0;
        if((fd = open(myfifo, O_RDONLY)) < 0){//只读 
            perror("FunctI/On customing error");
            return -1;
        }
        printf("Enjoy:");
        lseek(fd, SEEK_SET, 0);
        while(counter < need){
           
           while((read(fd, &buf, 1) == 1) && (counter < need)){//read期望读取的字符数与实际所读一样&&.... 
              fputc(buf, stdout);//打印到显示屏 
              counter ++;
           }
           
        }
        fputs("\n", stdout);
         

        close(fd);
        return 0;
}                                                                                                         

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){//非阻塞只读 
            perror("FunctI/On my filecopy error int source file\n");
            return -1;
        }

        if((out_file = open(dest_file, O_RDWR|O_CREAT|O_TRUNC|O_NONBLOCK, 0664)) < 0){//非阻塞&打开或创建 
            perror("FUNCTI/O myfilecopy error in destinatI/on 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;
}

 int custom(int need){
         int fd;
         customing(fifo_file, need);//取
 
         if((fd = open(fifo_file, O_RDWR)) < 0){//读写方式打开 
             perror("FunctI/On myfilecopy error in source_file");
             return  -1;
         }
 
         lock_set(fd, F_WRLCK);//上锁,写入锁 
         myfilecopy(fifo_file, temp_file, need, MAX_FILE_SIZE, 0);//将第一个文件内容复制到另一个文件,偏移>
         myfilecopy(temp_file, fifo_file, 0, MAX_FILE_SIZE, 0);
         lock_set(fd, F_UNLCK);//解锁 
 
         unlink(temp_file);//删除 
 
         close(fd);
         return 0;
 }

 int main(int argc, const char *argv[]){
         int customer_capacity = 0;
 
             if(argc > 1){
                sscanf(argv[1], "%d", &customer_capacity);//消费数目写入 
             }
 
             if(customer_capacity > 0){
               custom(customer_capacity);
             }
 
             return 0;
 }

这里对open函数进行再次扩充讲解:

当文件被一个进程植入写入锁的时候,另一个进程仍可以通过open函数获取该文件的标志位,但却不能进行read或write函数操作,因为会受到写入锁的阻止

朴素的将写入锁是阻止其他进程对文件的读写操作,而不是open操作

在这里插入图片描述
之前一直不理解为什么下列语句不会报错,通过用printf函数取点才发现问题

if((fd = open(myfifo, O_RDONLY)) < 0){//只读 
        perror("FunctI/On customing error");
        return -1;
}

看来看课本和懂课本是天差地别的

还有一点注意的是:

生产者代码中的:

while(time_life --){
	if(product() < 0){
		break;
	} 
	sleep(time_step);
}

其中:

sleep(time_step);

这个延时语句作用巨大:

lock_set(fd, F_WRLCK);//上锁,写入锁 
myfilecopy(fifo_file, temp_file, need, MAX_FILE_SIZE, 0);//将第一个文件内容复制到另一个文件,偏移>
myfilecopy(temp_file, fifo_file, 0, MAX_FILE_SIZE, 0);
lock_set(fd, F_UNLCK);//解锁

其作用是为了让消费者中这个文件挪动语句能有时间完成

例如文件中生产abc,消费a,所以挪位后为abc

效果:

已生产五个字符:
在这里插入图片描述

消费四个:
在这里插入图片描述

最后剩一个:

在这里插入图片描述

同时进行如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1149651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

钢琴培训答题服务预约小程序的效果怎样

很多家长都会从小培养孩子的兴趣&#xff0c;钢琴便是其中热度较高的一种&#xff0c;而各城市也不乏线下教育培训机构&#xff0c;除了青少年也有成年人参加培训&#xff0c;市场教育高需求下&#xff0c;需要商家不断拓展客户和转化。 那么通过【雨科】平台制作钢琴培训服务…

机器狗装上 ChatGPT 大脑当导游;AI 正在学习「超人的说服力」丨 RTE 开发者日报 Vol.73

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

C++进阶语法——智能指针【学习笔记(五)】

文章目录 1、智能指针简介1.1 原始指针&#xff08;raw pointer&#xff09;的⼀些问题1.2 智能指针&#xff08;smart pointers&#xff09; 2、智能指针&#xff08;smart pointers&#xff09;——unique_ptr2.1 unique_ptr 的声明2.2 unique_ptr 的函数2.3 ⾃定义类型使⽤ …

需要下微信视频号视频的小伙伴们看过来~

随着视频号的热度越来越大&#xff0c;下载视频号视频的需求也开始增加啦&#xff0c;今天给大家给分享几个简单实用的下载方法&#xff0c;总有一个你能用上的&#xff01; 一、犀牛视频下载 犀牛视频下载器可以直接解析并下载视频号短视频。您只需转发视频到机器人即可下载。…

中科驭数受邀亮相两场重要行业盛会,摘得2023“璀璨技术奖”奖项

近日&#xff0c;中科驭数作为DPU算力基础设施领军企业&#xff0c;受邀参与2023信息技术应用创新专题研讨会暨第二届集成电路产业发展创新大会、以及2023AI网络创新大会。在两大行业盛会上&#xff0c;中科驭数与行业知名专家和企业代表齐聚一堂&#xff0c;分享了DPU在集成电…

蓝凌EIS智慧协同平台saveImg接口存在任意文件上传漏洞

蓝凌EIS智慧协同平台saveImg接口存在任意文件上传漏洞 一、蓝凌EIS简介二、漏洞描述三、影响版本四、fofa查询语句五、漏洞复现六、深度复现1、发送如花2、哥斯拉直连 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者…

拿下国家级信创认证 中科驭数KPU SWIFT-2200N成为国内首款满足金融业严苛要求的DPU产品

近日&#xff0c;中科驭数KPU SWIFT-2200N低时延DPU卡&#xff0c;在中国人民银行旗下金融信创生态实验室完成测试并取得测试报告&#xff0c;这意味着中科驭数低时延网络代表性产品的应用领域从证券进一步拓展到了银行业&#xff0c;成为国内首款满足金融行业严苛要求的DPU产品…

vue2+antd——实现动态菜单路由功能——基础积累

vue2antd——实现动态菜单路由功能——基础积累 实现的需求&#xff1a;效果图&#xff1a;登录接口处添加以下代码loadRoutes方法内容如下&#xff1a; 最近在写后台管理系统&#xff0c;遇到一个需求就是要将之前的静态路由改为动态路由&#xff0c;使用的后台框架是&#xf…

#智能小车项目(六)麦克纳姆轮x型运动学分析

麦伦介绍 瑞典麦克那姆公司发明的一种全方位移动轮式结构&#xff0c;由基于主体轮辋和一组均匀排布在轮毂周围的回转辊子组成且辊子轴线与轮毂轴线呈一定角度(一般为 45)&#xff0c;小辊子的母线是等速螺旋线或椭圆弧近似而成&#xff0c;当轮子绕着轮毂轴线转动时&#xff…

css画一条虚线,用到background-image:linear-gradient线性渐变的属性

CSS实现虚线的方法_css 虚线_saltlike的博客-CSDN博客 渐变属性(background-image)全解析_background-image linear_大聪明码农徐的博客-CSDN博客 Background:linear-gradient()详解_background: linear-gradient_小白白中之白的博客-CSDN博客 注意&#xff1a; 必须要写高…

QMI8658A_QMC5883L(9轴)-EVB 评估板

1. 描述 QMI8658A_QMC5883L(9轴)-EVB 评估板是一款功能强大的9轴IMU传感器&#xff0c;它利用了QMA8658A 内置的3轴加速度计和3轴陀螺仪&#xff0c;同时结合QMC5883L的3轴地磁数据&#xff0c;来测量物体在三维空间中的角速度和加速度&#xff08;严格意义上的IMU只为用户提供…

在MDP环境下训练强化学习智能体

目录 1.创建MDP环境 2.创建Q-learning智能体 3. 训练Q-learning智能体 4.验证Q-learning结果 本文示例展示了如何训练Q-learning智能体来解决一般的马尔可夫决策过程(MDP)环境。有关这些智能体的更多信息&#xff0c;请参阅Q-Learning智能体。 MDP环境如下图&#xff1a; …

浙江爱知道控股集团,数字化经营的实践者,科技降本增效,助力基业长青

拥抱时代浪潮&#xff0c;加速科技变革。10月27日&#xff0c;浙江爱知道控股集团于西子智慧产业园西子音乐厅举办“AIGC可持续发展峰会”&#xff0c;重点探讨了数字化经营的重要意义。 提高效率和降低成本&#xff1a;数字化经营可以优化和自动化企业的业务流程&#xff0c;提…

Chrome浏览器Snippets调试面板

用Chrome的snippets片段功能创建页面js外挂程序&#xff0c;从控制台创建js小脚本。 Chrome的snippets是小脚本&#xff0c;还可以创作并在Chrome DevTools的来源面板中执行。 可以访问和从任何页面运行它们。当你运行一个片段&#xff0c;它从当前打开的页面的上下文中执行。 …

达索系统SOLIDWORKS 2024 装配体新增功能

如今市场环境紧迫&#xff0c;许多企业在这样的情形之下&#xff0c;都需要尽快将产品推向市场&#xff0c;赢得头筹。所以产品设计需要快速进行装配验证&#xff0c;以确保产品功能和性能的准确性和可靠性&#xff0c;同时原型或样机的制造和装配需要尽快完成&#xff0c;以满…

HEC-RAS模型教程

详情点击公众号链接&#xff1a;HEC-RAS模型教程 前言 水动力与水环境模型的数值模拟是实现水资源规划、环境影响分析、防洪规划以及未来气候变化下预测和分析的主要手段。 一&#xff0c;水动力模型 1.水动力模型的本质 2.水动力模型的基本方程与适用范围 3.模型建模要点…

地球系统模式CESM

目前通用地球系统模式&#xff08;Community Earth System Model&#xff0c;CESM&#xff09;在研究地球的过去、现在和未来的气候状况中具有越来越普遍的应用。CESM由美国NCAR于2010年07月推出以来&#xff0c;一直受到气候学界的密切关注。近年升级的CESM2.0在大气、陆地、海…

接口测试,一篇搞定

大多数人对于接口测试都觉得是一种高大上的测试&#xff0c;觉得学会接口测试就可以从小白测试员&#xff0c;变成了高级测试员&#xff0c;但其实接口测试只是测试的基础内容 什么是接口 接口泛指实体把自己提供给外界的一种抽象化物&#xff08;可以为另一实体&#xff09;&…

Java List Set Map

一、List 1.1 ArrayList 1.2 LinkedList 二、Set 2.1 HashSet 2.2 TreeSet 2.3 LinkedHashSet 三、Map 3.1 HashMap 3.2 TreeMap 3.3 LinkedHashMap 四、对比 类型底层结构重复null值场景备注查询删除新增ListArrayList动态数组可允许快速随机访问元素0(1)0(n)尾部增加0&a…