有限状态机--实现cp的功能

news2025/1/18 9:51:10

有限状态机–实现cp的功能

执行的任务

image-20230818121859373

上图是我们想实现的任务,对于A机来说,从fd1读取内容写到fd2,B机要做的是从fd2读取内容写到fd1中。

画出A机的状态。

image-20230818121826684

代码示例

fsm.c

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

#define TTY1 "/dev/tty3"
#define TTY2 "/dev/tty4"
#define BUFSIZE 1024

// 有限状态机的状态枚举
enum {
    STATE_R = 1, // 读
    STATE_W, // 写
    STATE_Ex, // 异常
    STATE_T // 终止
};

struct fsm_st {
    int state;//当前状态机的状态
    int sfd;
    int dfd;
    int len; // 读取到的数据
    int pos; // buf的偏移量
    char buf[BUFSIZE]; // 缓冲区
    char *errstr; // 报错信息
};

/* 状态机驱动 */
static void fsm_driver(struct fsm_st *fsm) {
    int ret;
    // 根据当前状态,决定下一步动作
    switch(fsm->state) {
        // 当前状态为读状态
        case STATE_R:
            //读取len长度的内容,下次进来会使用,所以要保存在结构体中
            fsm->len = read(fsm->sfd, fsm->buf, BUFSIZE);
            if(fsm->len == 0) { // 读到文件末尾,准备退出进程
                fsm->state = STATE_T;
            }else if(fsm->len < 0) {
                if(errno == EAGAIN) { // 假错,置为 读态
                    fsm->state = STATE_R;
                } else { // 真错,置为 退出态
                    fsm->errstr = "read()";
                    fsm->state = STATE_Ex;
                }
            }else { // 读取成功,置为 写状态
                fsm->pos = 0;
                fsm->state = STATE_W;
            }
            break;
        // 当前状态为写状态
        case STATE_W:
            ret = write(fsm->dfd, fsm->buf + fsm->pos, fsm->len);
            if(ret < 0) {
                if(errno == EAGAIN) {
                    fsm->state = STATE_W;
                } else {
                    fsm->errstr = "write()";
                    fsm->state = STATE_Ex;
                }
            }else {
                fsm->pos += ret;
                fsm->len -= ret;
                if(fsm->len == 0) { // 写够len个字节
                    fsm->state = STATE_R;
                } else { // 没有写够len个字节
                    fsm->state = STATE_W;
                }
            }
            break;
        //当前状态为错误态
        case STATE_Ex:
            perror(fsm->errstr);
            fsm->state = STATE_T;
            break;
        //终止态
        case STATE_T:
            break;
        default:
            abort();
            break;
    }
}

static void relay(int fd1, int fd2) {
    int fd1_save, fd2_save;
    struct fsm_st fsm12, fsm21;
    
    // 获取文件属性信息
    fd1_save = fcntl(fd1, F_GETFL);
    // 设置文件属性信息,设置为非阻塞模式
    fcntl(fd1, F_SETFL, fd1_save|O_NONBLOCK);

    fd2_save = fcntl(fd2, F_GETFL);
    fcntl(fd2, F_SETFL, fd2_save|O_NONBLOCK);
    
    //设置状态机初始状态和其他信息
    fsm12.state = STATE_R;
    fsm12.sfd = fd1;
    fsm12.dfd = fd2;

    fsm21.state = STATE_R;
    fsm21.sfd = fd2;
    fsm21.dfd = fd1;
	// 轮询,只要A机或B机不是退出态就执行读、写的工作
    while(fsm12.state != STATE_T || fsm21.state != STATE_T) {
        fsm_driver(&fsm12);
        fsm_driver(&fsm21);
    }

    // 恢复设备文件原本的属性
    fcntl(fd1, F_SETFL, fd1_save);
    fcntl(fd2, F_SETFL, fd2_save);
}


// 在main函数中模拟用户设置
int main(void) {
    int fd1, fd2; 
    
    // 假设用户以阻塞的方式打开设备文件
    if((fd1 = open(TTY1, O_RDWR)) < 0) {
        perror("open()");
        exit(1);
    }
    write(fd1,"TTY1\n",5);
    
    // 假设用户以非阻塞的方式打开设备文件
    if((fd2 = open(TTY1, O_RDWR|O_NONBLOCK)) < 0) {
        perror("open()");
        exit(1);
    }
    write(fd2,"TTY2\n",5);
    
    relay(fd1, fd2);
    
    close(fd2);
    close(fd1);

    exit(0);
}

将上述代码编译执行,运行后占用CPU多,原因是因为总是在假错地方循环,判断。

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

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

相关文章

ShowMeBug CEO李亚飞受邀参加深圳青年创新创业系列沙龙电子信息专场

7月13日下午&#xff0c;由深圳市科技交流服务中心&#xff08;深圳市科技专家委员会办公室&#xff09;主办&#xff0c;深圳新一代产业园承办的“2023深圳青年创新创业系列沙龙——电子信息专场”活动举行。ShowMeBug CEO李亚飞受邀参加此次活动。 深圳市科学技术协会党组成员…

web JS高德地图标点、点聚合、自定义图标、自定义窗体信息、换肤等功能实现和高复用性组件封装教程

文章目录 前言一、点聚合是什么&#xff1f;二、开发前准备三、API示例1.引入高德地图2.创建地图实例3.添加标点4.删除标点5.删除所有标点&#xff08;覆盖物&#xff09;6.聚合点7.自定义聚合点样式8.清除聚合9.打开窗体信息 四、实战开发需求要求效果图如下&#xff1a;封装思…

nginx php-fpm安装配置

nginx php-fpm安装配置 nginx本身不能处理PHP&#xff0c;它只是个web服务器&#xff0c;当接收到请求后&#xff0c;如果是php请求&#xff0c;则发给php解释器处理&#xff0c;并把结果返回给客户端。 nginx一般是把请求发fastcgi管理进程处理&#xff0c;fascgi管理进程选…

基于YOLOX的输电线路异物检测算法研究及软件设计_有系统有文献,整体认知蛮好的

我国自改革开放以来&#xff0c;大力发展工业和经济&#xff0c;对电能同样有着巨大的需求&#xff0c;所需求的电能不仅需要保证其数量&#xff0c;还要保障其质量&#xff0c;因此对整个电力系统安全稳定的运行也提出了更高的要求&#xff0c;电力系统发生故障要实时检测并及…

从零做软件开发项目系列之一综论软件项目开发

1 引言 有一个三个泥瓦匠的故事。 三个泥瓦匠在砌墙&#xff0c;一个人走过来&#xff0c;问他们在干什么。   第一个泥瓦匠没好气地说&#xff0c;你没看见吗&#xff1f;我在辛苦地砌墙呢。   第二个回答&#xff0c;我们正在建一座高楼。   第三个则洋溢着喜悦说&…

Vue2子组件修改父组件的方法

Vuex Vuex 是状态管理器&#xff0c;集中式存储管理所有组件的状态。 Vuex速成整理_AYBAIWAN的博客-CSDN博客https://blog.csdn.net/aybaiwan/article/details/131442547?spm1001.2014.3001.5501vuex中this.$store.commit和this.$store.dispatch的用法_老电影故事的博客-CSD…

第八届XCTF联赛首场国际外卡赛——WACON2023即将开启!

由国际战队SuperGuesser操刀命题 第八届XCTF首场国际外卡赛 WACON2023即将开启 线上资格赛前6名队伍 将晋级WACON2023总决赛 飞往韩国首尔 与全球顶尖白帽黑客一决高下 总决赛冠军队伍将获得&#xff1a; 3千万韩元&#xff08;折合人民币16万&#xff09;高额奖金 &第八…

Java IO流(一)IO基础

概述 IO流本质 I/O表示Input/Output,即数据传输过程中的输入/输出,并且输入和输出都是相对于内存来讲Java IO(输入/输出)流是Java用于处理数据读取和写入的关键组件常见的I|O介质包括 文件(输入|输出)网络(输入|输出)键盘(输出)显示器(输出)使用场景 文件拷贝&#xff08;File&…

基于Java的深圳坂田附近闲置物品交易群管理系统

开发技术&#xff1a;java 开发框架&#xff1a;springmvc、spring、mybatis 数据库&#xff1a;mysql 备注&#xff1a;方便大家将手中的二手闲置物品转让给需要的人&#xff0c;例如大家搬家的时候&#xff0c;有不要的&#xff08;冰箱、洗衣机、桌子、椅子&#xff09;等物…

【3519DV500】AI算法承载硬件平台_2.5T算力+AI ISP图像处理_超感光视频硬件方案开发

Hi3519DV500 内置双核 A55 &#xff0c;提供高效、丰富和灵活的CPU 资源&#xff0c;以满足客户计算和控制需求。 Hi3519DV500集成了高效的神经网络推理引擎&#xff0c;最高2.5Tops NN算力&#xff0c;支持业界主流的神经 网络框架。神经网络支持完整的 API 和工具链&#xf…

Qt使用qml(QtLocation)显示地图

一、qt版本和QtLocation模块版本确认 如果qt版本过低的话是没有QtLocation模块的&#xff0c;我的版本如下 构建工具版本如下 二、qml代码编写 1、工程中添加模块 首先在工程中添加模块quickwidgets positioning location 2、添加资源文件 3、在资源文件中添加qml文件 …

什么是卷积神经网络

目录 什么是卷积神经网络 全链接相对笨重&#xff1a;大胖子​编辑 ​编辑 参数众多&#xff1a;容易造成过拟合 ​编辑 卷积核&#xff1a;进行图像特征提取&#xff0c;源于卷积原理&#xff1a;求相交面积 卷积的作用 卷积的意义 ​编辑 通过卷积核减少参数 深度卷积…

【001】ts学习笔记-准备工作和【基本类型】

typescript安装的包 npm i typescript #安装ts npm i types/node --save-dev # TypeScript 项目中使用类型检查和自动补全。 npm i ts-node -g #可直接在nodejs环境中使用ts, 如&#xff1a;ts-node example.tstsc 常用命令 tsc -init #生成tsc目录下的配置文件:tsconfig.jso…

ADAS-干货|自动驾驶汽车E/E拓扑架构与软件功能框架

引言 之前在公众号中我们对自动驾驶常见传感器的原理进行了讲解&#xff0c;如《可见光相机》《IMU惯导传感器》《GPS传感器原理》《毫米波雷达原理》以及《激光雷达原理》。今天我们将结合TI自动驾驶部门专家发表的相关的论文&#xff0c;讲解现代自动驾驶汽车车身电气架构以及…

dockerfile的概念

目录 一、Dockerfile 概念 1.1 docker镜像的分层 二、Docker镜像的创建 2.1 基于已有的镜像创建 2.2 基于本地模板创建 2.3 基于dockerfile创建 2.3.1 dockerfile 结构(四部分) 三、Dockerfile操作指令 3.1 ENTRYPOINT指令 3.2 CMD 与entrypoint 3.3 小结 四、ADD和…

STM32——SPI外设总线

SPI外设简介 STM32内部集成了硬件SPI收发电路&#xff0c;可以由硬件自动执行时钟生成、数据收发等功能&#xff0c;减轻CPU的负担 可配置8位/16位数据帧、高位先行/低位先行 时钟频率&#xff1a; fPCLK / (2, 4, 8, 16, 32, 64, 128, 256) 支持多主机模型、主或从操作 可…

Pandas+Pyecharts | 成都大运会奖牌数据分析可视化

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 数据信息2.3 数据处理 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 每日奖牌数量分布3.2 奖牌榜单TOP20金银铜牌分布3.3 各比赛项目金牌…

Java“牵手“拼多多商品详情页面数据获取方法,拼多多API实现批量商品数据抓取示例

拼多多商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取拼多多商品详情数据&#xff0c;您可以通过开放平台的接口或者直接访问拼多多商城的网页来获取商品详情信息。以下是两种常用方法的介绍&#xff1a;…

使用el-tree实现自定义树结构样式

实现结果&#xff1a; 直接上代码&#xff1a; <template><div><div class"tops"><el-tree :default-expanded-keys"[1]" ref"myTree" :data"data" :props"defaultProps" node-click"handleNod…

IO的几个模型

I/O模型名词介绍 说到I/O模型&#xff0c;都会牵扯到同步、异步、阻塞、非阻塞这几个词&#xff0c;以下讲解这几个词的概念。 阻塞和非阻塞 阻塞和非阻塞指的是一直等还是可以去做其他事。 阻塞&#xff08;blocking&#xff09;&#xff1a;调用结果返回之前&#xff0c;…