嵌入式Linux开发的编程语言选择

article/2025/9/22 8:45:15

欢迎大家关注我的公*号:embedded_bug

这里的嵌入式Linux环境是指非标准Linux发行版环境,比如通过buildroot创建的,相比于标准的Linux发行版比如ubuntu,debian,fedora,系统比较简陋,提供的库很有限,而且系统的各种配置文件和配置方式与标准Linux发行版差别很大,总之,这里的嵌入式Linux只保证系统能够基本的启动运行起来。

在这里插入图片描述

上图是现在编程语言的流行度排名,别看这么多语言,真正适合在嵌入式Linux中应用的并不多。

直接说结论,个人推荐:go>C++(11)+boost>c,其他语言目前还都不太适合。

本篇文章先讨论C和C++,下面一篇文章讨论go及其他语言。

一、C语言,迫不得已的选择

​ C语言作为最基本的编程语言,只要是个嵌入式Linux环境肯定都是支持的,但是同样使用C的问题很多,包括:

  • 语言比较老旧,很多高级语言的特性比较缺乏,程序写起来比较费时间,容易出错,代码行数也多。

  • 基础C库功能太少,需要什么新功能还得去找相当的函数库,然后交叉编译,测试函数库功能怎么样,是否满足需求,费时费力。

    总之,C语言的问题是库少,写起来费事,容易出错。优点是程序运行速度快,空间占用小。

二、C++(基于11标准,配合boost库),不能用go时候的选择

选择C++有两个条件,基于C++11标准编写程序,并配合boost库。如果还是用C的思想在用C++,那还不如直接用C。使用C++,一定要将C++当成一个不同于C的全新语言使用,否则发挥不出C++的优势。

C++11相比于之前的C++是巨大的进步,并且gcc4.8.5的版本已经能够完整支持C++11了。C++11的特性包括自动类型推导,自动指针,lamba表达式等等。代码写起来更流畅,更精简了。唯一的缺点就是太复杂了,否则也就没go什么事了。

​ boost库为什么是一个必选项呢,因为boost库实在太强大了,嵌入式开发百分之九十以上的需求都可以通过boost库实现,完全不需要借助第三方库,包括串口操作boost库中都包含了。并且boost库大部分是头文件,交叉编译出来的so文件也并不大,占用不了太多空间。

​ https://www.boost.org/doc/libs/1_76_0/

看下boost的文档,你就知道boost库的功能有多强大。

C++11+boost库的缺点就是太复杂,学习起来比较困难,不过真要用熟了,绝对就成了C++大师了,跳槽升职加薪迎娶白富美走向人生巅峰不是梦!

下面列举几个C++ boost库的代码示例

用boost库解析命令行参数:

using namespace std;
namespace bpo = boost::program_options;
namespace blog = boost::log;
namespace baio = boost::asio;// 解析命令行参数
int initFlag(int argc, char* argv[], string &configDir, string &logDir, int &logLevel) 
{//步骤一: 构造选项描述器和选项存储器//选项描述器,其参数为该描述器的名字bpo::options_description opts("all options"); //选项存储器,继承自map容器bpo::variables_map vm;//步骤二: 为选项描述器增加选项//其参数依次为: key, value的类型,该选项的描述opts.add_options()("configdir", bpo::value<string>()->default_value("./"), "set config file dir")("logdir", bpo::value<string>()->default_value("./"), "set log file dir")("loglevel", bpo::value<int>()->default_value(4), "set log level 0-6 panic fatal error warn info debug trace")("help,h", "this is a log test program");//步骤三: 先对命令行输入的参数做解析,而后将其存入选项存储器//如果输入了未定义的选项,程序会抛出异常,所以对解析代码要用try-catch块包围try{//parse_command_line()对输入的选项做解析//store()将解析后的结果存入选项存储器store(parse_command_line(argc, argv, opts), vm);}catch(...){cout << "command line param is not correct" << endl;cout << opts << endl;   return -1;}//步骤四: 参数解析完毕,处理实际信息if(vm.empty())		//这里不会为空,因为设置了默认值{}//count()检测该选项是否被输入if(vm.count("help") ){//若参数中有help选项//options_description对象支持流输出, 会自动打印所有的选项信息cout << opts << endl;   return 1;}//variables_map(选项存储器)是std::map的派生类,可以像关联容器一样使用,//通过operator[]来取出其中的元素.但其内部的元素类型value_type是boost::any,//用来存储不确定类型的参数值,必须通过模板成员函数as<type>()做类型转换后,//才能获取其具体值.if(vm.count("configdir") ){configDir = vm["configdir"].as<string>();}if(vm.count("logdir") ){logDir = vm["logdir"].as<string>();}if(vm.count("loglevel") ){logLevel = vm["loglevel"].as<int>();}return 0;
}

用boost库进行日志记录,同时记录至终端和文件中,并且文件支持自动分割,自动删除:

using namespace std;
namespace bpo = boost::program_options;
namespace blog = boost::log;
namespace baio = boost::asio;// 初始化日志,日志级别0-6 panic fatal error warn info debug trace
int initLog(string logPre, string logdir,  int logLevel) 
{if ((logdir.length() > 0) && (*(--logdir.end()) == ':')){logdir += "/";}// 设置日志同时输出至文件和标准输出auto console_sink = blog::add_console_log(std::cout,blog::keywords::format = (blog::expressions::stream<< blog::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")<< " - [" << blog::trivial::severity<< "] : " << blog::expressions::smessage),blog::keywords::auto_flush = true);auto file_sink = blog::add_file_log(blog::keywords::file_name = logPre + ".log",// blog::keywords::target_file_name  = logPre + "_%Y%m%d_%3N.log",blog::keywords::enable_final_rotation = false,blog::keywords::rotation_size = 1 * 1024 * 1024,// blog::keywords::time_based_rotation = blog::sinks::file::rotation_at_time_point(0, 0, 0),blog::keywords::format = (blog::expressions::stream<< blog::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")<< " - [" << blog::trivial::severity<< "] : " << blog::expressions::smessage),blog::keywords::auto_flush = true,blog::keywords::open_mode = ios_base::app);file_sink->locked_backend()->set_file_collector(blog::sinks::file::make_collector(blog::keywords::target = logdir,        //folder name.blog::keywords::max_size = 3 * 1024 * 1024    //The maximum amount of space of the folder.// blog::keywords::min_free_space = 100 * 1024 * 1024  //Reserved disk space minimum.));file_sink->locked_backend()->scan_for_files();// 设置日志输出级别blog::trivial::severity_level logsevirity[]{ blog::trivial::fatal, blog::trivial::fatal, blog::trivial::error, blog::trivial::warning, blog::trivial::info, blog::trivial::debug, blog::trivial::trace};// console_sink->set_filter(blog::trivial::severity >= logsevirity[LogLevel]);file_sink->set_filter(blog::trivial::severity >= logsevirity[logLevel]);        // 只有文件过滤日志blog::add_common_attributes();return 0;
}void logFunc(int Id)
{BOOST_LOG_TRIVIAL(trace) << Id << "A trace severity message";BOOST_LOG_TRIVIAL(debug) << Id << "A debug severity message";BOOST_LOG_TRIVIAL(info) << Id << "An informational severity message";BOOST_LOG_TRIVIAL(warning) << Id << "A warning severity message";BOOST_LOG_TRIVIAL(error) << Id << "An error severity message";BOOST_LOG_TRIVIAL(fatal) << Id << "A fatal severity message";
}

用boost库进行串口读写

using namespace std;
namespace bpo = boost::program_options;
namespace blog = boost::log;
namespace baio = boost::asio;void serialFunc(void)
{try{baio::io_service io_context;baio::serial_port sp(io_context);sp.open("/dev/ttyS2");//设置串口参数sp.set_option(baio::serial_port::baud_rate(9600));sp.set_option(baio::serial_port::flow_control());sp.set_option(baio::serial_port::parity());sp.set_option(baio::serial_port::stop_bits());sp.set_option(baio::serial_port::character_size(8));boost::system::error_code err;while(true){boost::array<char, 128> buf;boost::system::error_code error;size_t len = sp.read_some(baio::buffer(buf), error);if(error){throw boost::system::system_error(error); // Some other error.}BOOST_LOG_TRIVIAL(info) << "Serial recvd: " << buf.data();sp.write_some(baio::buffer(buf), error);if(err){throw boost::system::system_error(error); // Some other error.}}}catch(const std::exception& e){BOOST_LOG_TRIVIAL(error) << "Serial error: " << e.what();return;}
}

用boost库进行网络通信

using namespace std;
namespace bpo = boost::program_options;
namespace blog = boost::log;
namespace baio = boost::asio;void tcpClientFunc(void)
{try{baio::io_context io_context;baio::ip::tcp::tcp::resolver resolver(io_context);baio::ip::tcp::tcp::resolver::results_type endpoints =resolver.resolve("192.168.205.137", "60000");baio::ip::tcp::tcp::socket socket(io_context);baio::connect(socket, endpoints);BOOST_LOG_TRIVIAL(info) << "Tcp Client connect ok.";for (;;){boost::array<char, 128> buf;boost::system::error_code error;size_t len = socket.read_some(boost::asio::buffer(buf), error);if (error == boost::asio::error::eof){BOOST_LOG_TRIVIAL(warning) << "Tcp Client connect closed.";break; // Connection closed cleanly by peer.}else if (error){throw boost::system::system_error(error); // Some other error.}BOOST_LOG_TRIVIAL(info) << "Tcp Client recvd: " << buf.data();// std::cout.write(buf.data(), len);}}catch(const std::exception& e){BOOST_LOG_TRIVIAL(error) << "Tcp Client connect error: " << e.what();return;}
}void tcpServerChildFunc(baio::ip::tcp::tcp::socket sT)
{time_t now = time(0);string times = ctime(&now);for(;;){boost::system::error_code ignored_error;baio::write(sT, baio::buffer(times), ignored_error);if (ignored_error == boost::asio::error::eof){BOOST_LOG_TRIVIAL(warning) << "Tcp Server connect closed.";return;}else if (ignored_error){BOOST_LOG_TRIVIAL(error) << "Tcp Server connect error: " << boost::system::system_error(ignored_error).what();return;}this_thread::sleep_for(chrono::seconds(5));}
}
void tcpServerFunc(void)
{baio::io_context io_context;baio::ip::tcp::tcp::acceptor acceptor(io_context, baio::ip::tcp::tcp::endpoint(baio::ip::tcp::tcp::v4(), 60000));for (;;){try{baio::ip::tcp::tcp::socket socket(io_context);acceptor.accept(socket);auto t = thread(tcpServerChildFunc, move(socket));t.detach();}catch (std::exception &e){BOOST_LOG_TRIVIAL(error) << "Tcp Server accept error: " << e.what();}}
}

http://chatgpt.dhexx.cn/article/NL8tTfnc.shtml

相关文章

Linux如何修改系统语言

Linux如何修改系统语言 一、Linux如何修改系统语言 对于刚学Linux 的小伙伴&#xff0c;或者英语水平相对低一些的小伙伴&#xff0c;在自己的Linux系统里面如果能直接显示中文&#xff0c;中文提示就是比较爽的一件事了&#xff0c;接触起来也不会觉得头大&#xff0c;不过说…

将kali Linux系统的语言切换为中文

首先我们打开kali linux 虚拟机 。右键开启终端。.输入sudo apt install ttf-wqy- zenhei命令来下载中文语音包&#xff0c;这里我在第一次输入时没有加sudo命令&#xff0c;没有成功执行&#xff0c;原因是我的用户是普通用户&#xff0c;没有管理员权限&#xff0c;不能进行下…

linux 学习笔记(二)下载中文语言包

主页面是英文对我们对英语不太熟悉的人不是很友好&#xff0c;所以我们要下载中文语言包解决这一困难 首先我们需要换源&#xff0c;默认是美国源&#xff0c;下载很慢&#xff0c;甚至会失败。 1.搜索soft 2.选择最下面那一个 3.找到chain&#xff0c;推荐阿里源 在这里换源…

WPS Office 2019 For Linux 设置显示语言

点击右上角图标A&#xff0c;然后在弹出的对话框中选择中文&#xff0c;然后重启WPS即可

修改 Linux 系统默认语言为中文

最近在使用软件的时候&#xff0c;发现在不同的系统中&#xff0c;界面有时候显示中文&#xff0c;有时候显示英文。 后来发现是在软件启动的时候&#xff0c;读取系统的语言&#xff0c;于是需要参照下面的方式修改系统的语言 1、查看当前语言 locale下面 LANGen_US.UTF-8 …

将kali linux 的语言切换为中文

重置root密码 导入kali后&#xff0c;一般没有root密码&#xff0c;需要重置root密码的 使用sudo passwd root 命令重置密码 换源 因为默认源下载东西特别慢&#xff0c;所以我们需要换源 输入vim /etc/apt/sources.list&#xff0c;更改sources.list里面的源。 源的如下&…

如何更改linux的语言为英文

之前安装虚拟机的时候将语言设置为中文&#xff0c;装软件的时候发现有点不太好用&#xff0c;想改回英文界面。 在命令端输入&#xff1a;sudo vi /etc/default/locale可以看到一下界面&#xff1a; 按a可对其进行编辑&#xff0c;将上面的内容改为&#xff1a; 然后按Esc回…

linux系统设置成中文语言

既上篇文章后续 windows下安装ubuntu双系统&#xff08;详细完整版&#xff09;_缔宇diyu的博客-CSDN博客 打开设置&#xff0c;选择语言&#xff0c;点击管理安装语言 安装中文简体 将汉语拖到第一个&#xff0c;成为默认语言&#xff0c;然后点击应用于全局系统 输入密…

linux修改系统语言为中文

修改centos7系统语言 文章目录 修改centos7系统语言1.查看系当前语言包2.查看系统拥有语言包安装简体中文语言包临时修改永久修改方法(一)方法(二) 1.查看系当前语言包 locale2.查看系统拥有语言包 locale -a(zh_CN.UTF-8是简体中文&#xff0c;如果没有zh_CN.UTF-8,就安装语…

linux语言环境设置

Linux系统的语言环境设置之浅见在Linux的系统中经常碰到字符集导致的错误&#xff0c;下面总结了设置修改系统语言环境的方法。1.环境变量LANG用于设置系统的语言环境。当启动某些perl、php或其他编程的语言的程序文档时&#xff0c;都会主动去分析环境变量LANG的数据&#xff…

如何将kali linux语言设置成中文

1.进入root模式&#xff0c;执行dpkg-reconfigure locales命令。 2.找到en_US.UTF-8 UTF-8选项&#xff0c;按空格键将其进行取消。 3.选择语言zh_CN.UTF-8 UTP-8&#xff0c;空格选择&#xff0c;按tab键选择ok。 4.在此处选择zh_CN.UTF-8字符编码&#xff0c;在<0k> 处…

Linux之修改语言(语系)

今天要讲的是修改Linux当前支持的语言&#xff0c;大多数情况下大家用的都是en_US.UTF8 。当然了不同习惯的人可能用的语言是不一样的&#xff0c;下面就以date命令为例来看看不同的语言支持到底有什么差异。下然后来讲讲如何修改语言。 1、如下图所示&#xff0c;输入“echo …

linux C语言基础学习总结

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、思维导图二、linux基础1.常用命令2.vim编辑器3.gcc编辑器 三、C语言1.基础&#xff08;1&#xff09;.进制&#xff08;2&#xff09;词法符号&#xff08;3&am…

查看linux系统语言并修改

查看当前系统语言 登陆linux系统打开操作终端之后,输入 echo $LANG可以查看当前使用的系统语言。如 查看安装的语言包 查看是否有中

ADMM算法系列1:线性等式或不等式约束下可分离凸优化问题的ADMM扩展

1 研究背景 交替方向乘数法&#xff08;ADMM&#xff09;最初由Glowinski和Marrocco提出&#xff0c;用于解决非线性椭圆问题&#xff0c;它已成为解决各种凸优化问题的基准算法。在方法上&#xff0c;可以认为ADMM算法是在经典增广拉格朗日方法&#xff08;ALM&#xff09;的分…

Matlab代码:ADMM算法在考虑碳排放交易的电力系统最优潮流中的应用

Matlab代码&#xff1a;ADMM算法在考虑碳排放交易的电力系统最优潮流中的应用 关键词&#xff1a;交替方向乘子法&#xff0c; ADMM &#xff0c; 最优潮流 &#xff0c;碳排放&#xff0c; 分布式优化 仿真软件&#xff1a;Matlab软件调用cplex求解器进行求解 程序主要内容&am…

张量ADMM算法

ADMM被广泛用在张量中&#xff0c;下篇是找到的一篇文章&#xff1a; 从等式约束的最小化问题说起&#xff1a; 上面问题的拉格朗日表达式为&#xff1a; …

MATLAB代码:基于分布式ADMM算法的考虑碳排放交易的电力系统优化调度研究

MATLAB代码&#xff1a;基于分布式ADMM算法的考虑碳排放交易的电力系统优化调度研究 关键词&#xff1a;分布式调度 ADMM算法 交替方向乘子法 碳排放 最优潮流 参考文档&#xff1a;《A Distributed Dual Consensus ADMM Based on Partition for DC-DOPF with Carbon Emission …

对偶算法与ADMM算法

学习笔记&#xff0c;仅供参考&#xff0c;有错必纠 转载自&#xff1a;机器学习与运筹优化&#xff08;六&#xff09;对偶算法与ADMM算法 文章目录 摘要ADMM算法参考文献 摘要 上文我们介绍了约束优化问题和拉格朗日对偶思想。对偶算法就像是男生女生互相挑选&#xff0c;最…

【配电网优化】基于串行和并行ADMM算法的配电网优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…