前言 思路: Notice: EXP: 参考资料: 前言 不算很复杂的musl堆题,但是用了musl 1.2.2。 相比于musl 1.1.x中使用的以链表为主的类似dlmalloc的内存管理器,musl 1.2.2则采用了:malloc_context->meta_arena->meta->gropu (chunks ) 为了方便调试,可以下载一份musl-1.2.2源码然后用dir . /musl-1.2.2/src/malloc和dir . /musl-1.2.2/src/malloc\ndir .
LiteOS-M内核LibC实现有2种,可以根据需求进行二选一,分别是musl libC和newlibc。本文先学习下Musl LibC的实现代码。 LiteOS-M内核提供了和内核相关的文件系统、内存申请释放接口,其他接口可以直接使用Musl提供的。我们分别来看下内核提供的接口部分。 1、Musl LibC文件系统在使用Musl LibC并且使能支持POSIX FS API时,可以使用文件kal\libc\musl\fs.c中定义的文件系统操作接口。 其余的为文件状态标签,这些标签定义文件中third_party\musl\porting\liteos_m\kernel\include\bits\fcntl.h中。 参数中的struct stat结构体定义在文件third_party\musl\porting\liteos_m\kernel\include\bits\stat.h中。
例如在 RISC-V 架构上,基于 musl 的 systemd 可实现 1 秒内完成基础服务初始化。 OpenWRT 等项目已启动 systemd-musl 的移植工作,预计将替代部分 BusyBox 方案。在工业控制场景中,musl 的确定性行为(如固定内存分配策略)比 glibc 更受青睐。 Alpine Linux 等 musl 发行版需重建软件包生态,目前仅有 35% 的常用软件包完全兼容 musl 版 systemd。这可能延缓企业级采用速度。 例如,在服务器启动阶段使用 musl 快速初始化,运行阶段切换至 glibc 保障兼容性。 根据 IDC 预测,到 2027 年,musl 基础发行版在边缘计算设备的市场份额将从目前的 8% 增长至 23%,其中 systemd-musl 的贡献率将超过 60%。
rustup CI 现在正在构建 aarch64-musl 从而在ARM上为Alpine和postmarketOS启用完整的工具链。 reddit讨论: https://www.reddit.com/r/rust/comments/iumwxu/aarch64musl_now_being_built_by_rustup_ci_enabling
虽然一些 glibc 链接的共享库可以在 musl 下加载,但大多数 glibc 链接的应用程序如果直接替换为 musl 将会失败。 musl 环境下的 .NET 运行: musl 是一个轻量级的 C 库,常用于基于 musl 的 Linux 发行版,如 Alpine Linux。 在 musl 环境下,.NET 应用程序可能会遇到 musl 版本不匹配的问题。 .NET Core 3.0 及更高版本支持 musl,因此可以在 musl 环境下运行 .NET 应用程序。然而,musl 与 glibc 在某些方面存在差异,可能会导致兼容性问题。 在 musl 环境下,可以尝试降级 .NET 版本以匹配 musl 库,或者使用 Docker 容器来隔离运行环境。
我是自己编译了一个musl-gcc,下载: https://github.com/DragonOS-Community/musl-cross-make/releases/tag/9.4.0-231114 " make -j $(nproc) CC="riscv64-linux-musl-gcc" OBJCOPY=riscv64-linux-musl-objcopy STRIP=riscv64-linux-musl-strip RANLIB=riscv64-linux-musl-ranlib NM=riscv64-linux-musl-nm LD=riscv64-linux-musl-ld 然后当前目录下的”u-boot.bin TARGET_OBJCOPY=riscv64-linux-musl-objcopy TARGET_STRIP=riscv64-linux-musl-strip TARGET_RANLIB=riscv64 -linux-musl-ranlib TARGET_NM=riscv64-linux-musl-nm TARGET_LD=riscv64-linux-musl-ld make -j $(nproc)
opentelemetry-cpp 在标准上报协议OTLP里是支持使用 gRPC 作为传输协议的。但是,当 gRPC 被作为静态库同时链接进多个动态库时,在一些平台上会有一些问题。这是 gRPC 本身的一些实现方式导致的。 一直拖到今天才来比较完整得写这个问题的具体成因和解决方案,实际上也有一些其他库有相似实现的也会有相同的问题,所以分享出来看看有没有其他同学也可能碰到可以参考一下。
/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/ualarm.o [OHOS INFO] [1598/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src /third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/usleep.o[OHOS INFO] [1601 /1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src /obj/third_party/musl/intermidiates/linux/musl_src_ported/src/string/soft_musl_src_nossp/memset.o[OHOS
链接 musl libc,可以通过增加编译目标 x86_64-unknown-linux-musl 来实现。 这样做有一个问题,musl 的内存分配器没有进行速度优化,可能会降低应用程序的性能,尤其是在处理高吞吐量的应用程序时。 RUN apt update && apt install -y musl-tools musl-dev RUN update-ca-certificates # Create appuser ENV 由于基础镜像 alpine 基于 musl libc,因此它的约束条件与空镜像 scratch 相同,我们需要使用编译目标 x86_64-unknown-linux-musl,以静态链接我们的 Rust RUN apt update && apt install -y musl-tools musl-dev RUN update-ca-certificates # Create appuser ENV
为MUSL Libc构建 要针对MUSL libc进行构建,我们需要安装x86_64-unknown-linux-musl 构建目标,以便可以将Cargo标记为使用--target为其构建。 release --target=x86_64-unknown-linux-musl RUN rm -f target/x86_64-unknown-linux-musl/release/deps/myapp RUN RUSTFLAGS=-Clinker=musl-gcc cargo build --release --target=x86_64-unknown-linux-musl # ---------- =musl-gcc cargo build --release --target=x86_64-unknown-linux-musl 重新构建应用程序并运行它: docker build -t myapp RUN RUSTFLAGS=-Clinker=musl-gcc cargo build --release --target=x86_64-unknown-linux-musl # ----------
如果上面步骤没有错的话,应该很快就会看到 vs2017u5 exists, deleting 这一步骤很快就跳过了 跳过之后如果可以看到 linux-musl-x64 的下载,如以下输出内容 1>C:\ 也就是 1>Info: Using Runtime ID 'linux-musl-x64' 的 linux-musl-x64 号,也请记下 第三个信息是输出路径,也就是 1>C:\Windows\System32 -InstallPath "C:\Users\lindexi\vsdbg\vs2017u5\linux-musl-x64" 的 C:\Users\lindexi\vsdbg\vs2017u5\linux-musl-x64 文件夹 对比上面的步骤,可以看到是放在 vs2017u5 的 linux-musl-x64 文件夹 注意第二个信息的是 linux-musl-x64 和上面步骤的 linux-x64 不相同 接下来拼接下载路径 替换 vsdbg-(你的Runtime ID).zip 可以拿到 vsdbg-linux-musl-x64.zip 链接 拼接起来的链接大概如下,这个版本我放在 CSDN 上,点击 此链接 可以下载
\n"); } macOS 编译为 Linux 和 Windows 可用二进制程序 编译为 Linux 平台 想要实现Linux平台可以运行的程序,那么就需要使用musl来替代glibc,musl实现了 musl 在macOS上使用musl-cross,musl-cross是专门编译到Linux的工具链,下面进行安装: musl https://musl.libc.org/ $ brew install FiloSottile/musl-cross/musl-cross 还需要创建musl-gcc: $ ln -s /usr/local/bin/x86_64-linux-musl-gcc /usr/local (如果没有可以新建),添加以下内容: [target.x86_64-unknown-linux-musl] linker = "x86_64-linux-musl-gcc" 也可以在项目根目录下创建 . L 2 target/x86_64-unknown-linux-musl target/x86_64-unknown-linux-musl ├── CACHEDIR.TAG └── debug
在toolchain目录中解压gcc工具链压缩包和sysroot依赖压缩包,输入: tar -xzvf gcc-6.4-2017.11-x86_64_arm-openwrt-linux-eabi-musl.tar.gz ├── 100ask_t113-pro_arm-openwrt-linux-eabi-glibc_sysroot_v1.0.tar.gz ├── arm-openwrt-linux-eabi-musl ├── gcc-6.4-2017.11-x86_64_arm-openwrt-linux-eabi-musl.tar.gz ├── sysroot └── toolchain 进入gcc工具链文件目录的bin目录中查看交叉编译工具链是否存在 ubuntu@ubuntu1804:~/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/ CC为刚刚前面确认的交叉编译工具链路径,例如我刚刚确认的gcc交叉编译工具链绝对路径为: /home/ubuntu/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl
去年我发表了文章对Docker基础镜像的思考,该不该选择alpine,其中对于Alpine Linux镜像如此之小的原因我解释为它使用了musl而不是glibc 有人发现并指出了我的这个错误,说musl 我一直记着这事,最近抽时间再次研究了下,确实如其所说,Alpine Linux之所以这么小的原因,虽然musl是其中一个原因,但它是多种因素导致的。 如我在以前的文章中所述,Alpine中没有使用glibc,而是使用了musl,所以这一部分占据的大小也小了很多。 同时,通过在musl官网与glibc官网查阅它们的压缩安装包大小分别是: # musl 1.1MB musl-1.2.3.tar.gz # glibc 18M glibc-2.3.6.tar.gz 123K 使用Musl取代了Glibc 3.
build -o main-alpine $ ldd main-alpine linux-vdso.so.1 => (0x00007ffe0055e000) libc.musl-x86 _64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f2512958000) 可以看到, 缺失了 libc.musl-x86_64.so.1, 运行一下程序 /main-alpine: /lib/ld-musl-x86_64.so.1: bad ELF interpreter: No such file or directory No such file or 完整的出错信息可通过使用 Go 的 os/exec 包启动 main-alpine 获得) 解决方案 问题的原因在于云函数的运行环境(CentOS)提供的是 glibc, 而 Alpine Linux 却是 musl 因而使用 golang:1.13.1-alpine3.10 这个镜像编译出来的程序如果依赖于 musl libc, 则会在程序加载的时候找不到所需的动态库 解决问题的方法很简单, 只需将镜像换成 golang
而musl你可以理解它为一个更小,更轻量的C类库。 这就是最主要的原因。 四) 当然,这两者都支持C程序的编译与构建。也就是,大多数情况下,能在glibc上编译通过的也都能在musl上编译通过。 而主流Linux都是glibc,glibc的性能也高于musl的。 这意味着行业内的一个现状是:大多数在Linux上运行的软件,都是针对glibc进行测试过的,但针对musl,则不一定。 毕竟musl非常小众。 性能,musl的性能是稍差于glibc的 五) 再进一步,回到更小的镜像这一点上。 七) 最后,说下Java吧,因为Java依赖C类库,而支持Musl的Java实现,并非主流。
相比之下目前有另外一种专有的 musl 标准库实现,musl 被开发出来就是专注在内存受限的设备上表现优异,使用 musl 生产的二进制文件通常比使用 glibc 生产的文件体积更小,所以更推荐直接使用 musl 替代 glibc 去做编译链接优化。 基于 musl 编译的前置条件是依赖于 musl 工具链,但在 GraalVM JDK 中并未提供相关的工具链的支持,需要提前下载 x86_64-linux-musl-native 和 zlib 文件, /10/x86_64-linux-musl/x86_64-linux-musl-native.tgz# 解压下载到的 musl 工具链包tar -zxvf x86_64-linux-musl-native.tgz 通过 x86_64-linux-musl-gcc 和 musl 做链接编译生成的二进制可执行文件,完全使用的是静态链接的方式,从而提高了可移植性。
Generate按钮 (所有红色报错,全部关掉即可) 交叉编译工具链地址: /root/tina-v853-docker/prebuilt/rootfsbuilt/arm/toolchain-sunxi-musl-gcc toolchain/bin/arm-openwrt-linux-gcc /root/tina-v853-docker/prebuilt/rootfsbuilt/arm/toolchain-sunxi-musl-gcc toolchain/bin/arm-openwrt-linux-g++ /root/tina-v853-docker/prebuilt/rootfsbuilt/arm/toolchain-sunxi-musl-gcc 执行 export STAGING_DIR=/root/tina-v853-docker/prebuilt/rootfsbuilt/arm/toolchain-sunxi-musl-gcc-830/toolchain echo START rm -rf $(TARGET) /root/tina-v853-docker/prebuilt/rootfsbuilt/arm/toolchain-sunxi-musl-gcc
- echo $RUSTUP_UPDATE_ROOT - echo $CARGO_HOME - rustup target add x86_64-unknown-linux-musl - cargo build --release --target=x86_64-unknown-linux-musl - cd - ldd target/x86_64-unknown-linux-musl/release/xiu - strip -s target/x86_64-unknown-linux-musl application/xiu/src/config/config_rtmp.toml /conf/config_rtmp.toml COPY target/x86_64-unknown-linux-musl
- echo $RUSTUP_UPDATE_ROOT - echo $CARGO_HOME - rustup target add x86_64-unknown-linux-musl - cargo build --release --target=x86_64-unknown-linux-musl - cd - ldd target/x86_64-unknown-linux-musl/release/xiu - strip -s target/x86_64-unknown-linux-musl application/xiu/src/config/config_rtmp.toml /conf/config_rtmp.tomlCOPY target/x86_64-unknown-linux-musl