当前位置: 首页 > news >正文

趣味魔法项目 LinuxPDF —— 在 PDF 中启动一个 Linux 操作系统

最近,一位开源爱好者开发了一个LinuxPDF 项目(ading2210/linuxpdf: Linux running inside a PDF file via a RISC-V emulator),它的核心功能是在一个 PDF 文件中启动并运行 Linux 操作系统。它通过巧妙地使用 PDF 文件格式中的 JavaScript 功能,结合 Emscripten 技术,将一个 RISC-V 仿真器嵌入到 PDF 文件中,从而使得 Linux 系统能够在 PDF 中启动。并且可以直接在Chrome浏览器中直接打开(https://linux.doompdf.dev/linux.pdf),打开后如下图所示:

项目工作原理

1. PDF 文件支持 JavaScript

首先,提到 PDF,人们通常想到的是静态文档,通常包含文字、图片等元素,用于文档共享和打印。然而,PDF 文件实际上可以包含多种功能,包括嵌入 JavaScript。这使得 PDF 文件不仅仅局限于显示内容,还可以在其中嵌入交互式功能,甚至可以做一些很酷的计算和模拟任务。

这个项目的目的正是展示这种潜力。它通过将 RISC-V 仿真器 编译为 JavaScript,并嵌入到 PDF 文件中,模拟一个完整的 Linux 系统。虽然这并不意味着 PDF 文件会直接变成一个“操作系统”,但它展示了如何在不离开 PDF 阅读器的情况下运行一个简化的操作系统。

2. 技术实现:Emscripten 和 asm.js

为了将 Linux 系统放入 PDF 中,开发者使用了 Emscripten,一个开源工具链,能够将 C/C++ 代码编译为 JavaScript。Emscripten 支持将代码编译成两种格式:asm.js 或 WebAssembly。在这个项目中,使用的是 asm.js,一种 JavaScript 子集,专为提高性能而设计,允许 C 代码在浏览器中高效运行。

这个小小的“奇迹”是如何实现的呢?首先,开发者使用 TinyEMU,一个针对 RISC-V 架构 的仿真器,将它编译成 asm.js。这个 RISC-V 仿真器被嵌入到 PDF 文件的 JavaScript 中。换句话说,PDF 文件通过嵌入 JavaScript 代码来模拟一个完整的计算机系统。这个仿真器可以启动 Linux 内核,并运行一个简单的文件系统(带有 BusyBox)。

3. 虚拟化 Linux 系统

通过在 PDF 中嵌入该仿真器,用户可以启动一个 RISC-V 架构的 Linux 系统,尽管它的性能非常低。Linux 内核和文件系统被嵌入到 PDF 中,用户可以在 PDF 阅读器中使用它进行简单的操作。

4. 在 PDF 中交互:输入和输出

输入:

输入是通过虚拟键盘实现的,用户可以点击键盘上的按钮来向仿真器发送输入。仿真器的输入包括键盘按键,用户可以通过文本框输入命令,控制虚拟机。它还支持一些基本的输入设备模拟,如鼠标点击等。

输出:

仿真器的输出通过文本框来显示。每一行像素都对应一个单独的文本框,里面显示的是 ASCII 字符,这就是模拟器显示图形的方式。虽然这种方式比较原始,但它能够有效地在 PDF 文件中实现图形输出。

5. 解决性能问题:不可避免的“慢”速度

虽然这个项目在技术上非常有趣,但它也面临一个严重的性能瓶颈。由于 V8 引擎(Chrome PDF 引擎使用的 JavaScript 引擎)禁用了 JIT 编译,这导致代码执行效率极低,仿真速度非常慢。例如,Linux 内核启动可能需要 30 到 60 秒,这比正常运行慢了超过 100 倍!然而,这一切都可以理解,因为 JavaScript 的性能远远不如原生 C 代码,而且运行环境(PDF 阅读器)也是有限制的。

项目构建和运行

1. 克隆项目

首先,克隆该 GitHub 仓库。

git clone https://github.com/ading2210/linuxpdf.git 

2. 构建

使用虚拟环境来安装依赖:

python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txt
./build.sh
注意:
如果你想构建 64 位版本而不是 32 位版本,编辑 build.sh 文件,并将 BITS="32" 改为 BITS="64"。
build.sh 脚本会自动下载 Emscripten 1.39.20 版本。
你必须在 Linux 上构建。
生成的文件将位于 out/ 目录下。

3. 运行

构建完成后,你可以在本地启动一个 Web 服务器:并通过浏览器访问该 PDF 文件

cd out; python3 -m http.server

通过这些步骤,就可以通过浏览器访问该 PDF 文件,并在浏览器中运行一个嵌入了 Linux 系统的 PDF 文件,体验一个虚拟机在 PDF 阅读器中的运行。

总结

LinuxPDF 项目结合了深奥的计算机科学原理与一些非常酷的实现方式,展示了如何通过 PDF 文件实现 Linux 仿真。它不仅是对 PDF 格式潜力的挑战,也是对 JavaScript、Emscripten 和仿真技术的有趣展示。尽管这个项目的速度远远不能与传统的操作系统相比,但它却展示了PDF 文件格式在现代技术中可能扮演的新角色——不仅仅是静态文档,而是一个可以嵌入并运行计算任务的环境。这个项目证明了,PDF 不仅仅能用来展示信息,还能用来处理计算任务,甚至运行嵌入式系统。

此外,这种 PDF 中嵌入操作系统 的创意能够启发更多创新的应用,比如:

  • 在受限的环境中运行计算任务(如教育工具、嵌入式设备模拟)。
  • 用于将操作系统或应用程序打包到单一文件中,方便分发和使用。
  • 作为跨平台应用,尽管这需要处理性能和兼容性的问题。

相关文章:

趣味魔法项目 LinuxPDF —— 在 PDF 中启动一个 Linux 操作系统

最近,一位开源爱好者开发了一个LinuxPDF 项目(ading2210/linuxpdf: Linux running inside a PDF file via a RISC-V emulator),它的核心功能是在一个 PDF 文件中启动并运行 Linux 操作系统。它通过巧妙地使用 PDF 文件格式中的 Ja…...

win32汇编环境,窗口程序使用跟踪条(滑块)控件示例一

;运行效果 ;win32汇编环境,窗口程序使用跟踪条(滑块)控件示例一 ;生成2条横的跟踪条,分别设置不同的数值范围,设置不同的进度副度的例子 ;直接抄进RadAsm可编译运行。重要部分加备注。 ;下面为asm文件 ;>>>>>>>>>>>>>>>>>…...

mars3d接入到uniapp的时候ios上所有地图的瓦片都无法加载解决方案

用的是【Mars3d】官网的uniapp的仓库,安卓没有问题,但是ios的不行 相关链接 mars3d-uni-app: uni-app技术栈下的Mars3D项目模板 解决方案:感觉所有图片请求全被拦截了 uniapp的ios内核不允许跨域,需要先把瓦片下载后转base64&…...

使用 Notepad++ 编辑显示 MarkDown

Notepad 是一款免费的开源文本编辑器,专为 Windows 用户设计。它是替代记事本(Notepad)的最佳选择之一,因为它功能强大且轻量级。Notepad 支持多种编程语言和文件格式,并可以通过插件扩展其功能。 Notepad 是一款功能…...

wordpress主题制作

工具/原料 <P><BR>使用divcss语言编写的html静态页面一个</P> <P>Macromedia Dreamweaver软件<BR></P> WordPress主题结构分析 1 1、index.php首页模板&#xff08;最基本&#xff09; ---- 1、header.php头部 ---- 2、sidebar.php侧边…...

MybatisPlus常用增删改查

记录下MybatisPlus的简单的增删改查 接口概述 Service和Mapper区别 Mapper简化了单表的sql操作步骤&#xff08;CRUD&#xff09;&#xff0c;而Serivce则是对Mapper的功能增强。 Service虽然加入了数据库的操作&#xff0c;但还是以业务功能为主&#xff0c;而更加复杂的SQL…...

Citus的TPCC、TPCH性能测试

Citus的TPCC、TPCH性能测试 文章目录 Citus的TPCC、TPCH性能测试测试的目的适用范围测试环境架构信息硬件配置操作系统软件版本 测试结果TPCC测试测试结果TPCH测试测试结果 一、环境部署1.1、安装BenchmarkSQL1.2、PostgreSQL安装1.3、nmon部署1.4、TPC-H测试的生成数据工具安装…...

蓝桥杯---颜色分类(leetcode第75题)题解

文章目录 1.问题重述2.思路分析3.代码分析 1.问题重述 颜色分类&#xff0c;实际上就是赋予了三种颜色不同的数值&#xff0c;0,1,2分别代表的就是一个类型的颜色&#xff0c;我们题目说的是对于颜色进行分类&#xff0c;实际上就是对于0,1,2进行分类&#xff0c;我们把很多数…...

C语言基础13:循环结构 for和while

循环结构 什么是循环结构 代码在满足某种条件的前提下&#xff0c;重复执行&#xff0c;就叫做循环结构。 循环的分类 无限循环&#xff1a;其实就是死循环&#xff0c;程序设计中尽量避免无限循环&#xff0c;如果非要使用&#xff0c;那么这个循环一定要在可控范围内。有…...

六西格玛设计培训如何破解风电设备制造质量与成本困局

2023年&#xff0c;中国风电行业装机容量突破4.3亿千瓦&#xff0c;稳居全球第一&#xff0c;但高速扩张背后暗藏隐忧&#xff1a; 质量痛点&#xff1a;叶片开裂、齿轮箱故障等缺陷频发&#xff0c;运维成本占项目全生命周期成本超30%&#xff1b;成本压力&#xff1a;原材料…...

【Android开发】安卓手机APP使用机器学习进行QR二维码识别

前言:本项目是一个 Android 平台的二维码扫描应用,具备二维码扫描和信息展示功能。借助 AndroidX CameraX 库实现相机的预览、图像捕获与分析,使用 Google ML Kit 进行二维码识别。为方便大家了解项目全貌,以下将介绍项目核心代码文件 MainActivity.java 和 AndroidManifes…...

Zabbix-监控SSL证书有效期

背景 项目需要&#xff0c;需要监控所有的SSL证书的有效期&#xff0c;因此需要自定义一个监控项 实现 创建自定义脚本 在Zabbix的scripts目录(/etc/zabbix/scripts/)下创建一个新的shell脚本check_ssl.sh&#xff0c;内容如下 #!/bin/bash time$(echo | openssl s_client…...

生成式聊天机器人 -- 基于Pytorch + Global Attention + 双向 GRU 实现的SeqToSeq模型 -- 上

生成式聊天机器人 -- 基于Pytorch Global Attention 双向 GRU 实现的SeqToSeq模型 -- 上 前言数据预处理下载并加载数据原始数据格式化数据清洗与字典映射转换为模型需要的数据格式 SeqToSeq 模型Encoder 编码器Decoder 解码器全局注意力机制解码器实现 前言 本文会介绍使用…...

Kickstart自动化安装过程中自动选择较小的磁盘安装操作系统

Kickstart自动化安装过程中自动选择较小的磁盘安装操作系统 需求 在实际生成操作过程中&#xff0c;一般会遇到物理服务器存在多块盘的情况。 安装过程中&#xff0c;磁盘的标签是随机分配的&#xff0c;并不是空间较小的盘&#xff0c;就会使用较小的磁盘标签 而需求往往需要…...

基于进化式大语言模型的下一代漏洞挖掘范式:智能对抗与自适应攻防体系

摘要 本文提出了一种基于进化式大语言模型(Evolutionary LLM)的智能漏洞挖掘框架,突破了传统静态分析的局限,构建了具备对抗性思维的动态攻防体系。通过引入深度强化学习与多模态感知机制,实现了漏洞挖掘过程的自适应进化,在RCE、SQLi、XXE等关键漏洞类型的检测中达到97…...

游戏引擎学习第99天

仓库:https://gitee.com/mrxiao_com/2d_game_2 黑板&#xff1a;制作一些光场(Light Field) 当前的目标是为游戏添加光照系统&#xff0c;并已完成了法线映射&#xff08;normal maps&#xff09;的管道&#xff0c;但还没有创建可以供这些正常映射采样的光场。为了继续推进&…...

脉冲当量含义

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在开发C#的运动控制程序的时候&#xff0c;一个必要的步骤就是设置每个轴的脉冲当…...

docker compose部署flink集群

本次部署2个jobmanager和3个taskmanager 一、部署zookeeper集群 flink使用zookeeper用作高可用 部署集群参考&#xff1a;docker compose部署zookeeper集群-CSDN博客 二、创建目录及配置文件 创建timezone文件&#xff0c;内容填写Asia/Shanghai 手动创建目录&#xff1a…...

docker compose快速部署kafka-connect集群

先部署kafka集群&#xff0c;启动 参考&#xff1a;docker compose部署kafka集群-CSDN博客 创建timezone文件&#xff0c;内容填写Asia/Shanghai 再部署kafka-connect集群 networks: net: external: true services: kafka-connect1: restart: always image:…...

【核心特性】Go 模块化开发入门(go mod 深度解析)

Go 模块化开发入门&#xff08;go mod 深度解析&#xff09; 一、引言 在 Go 语言的开发过程中&#xff0c;随着项目规模的不断扩大&#xff0c;依赖管理变得愈发重要。Go Modules 作为 Go 语言官方的依赖管理工具&#xff0c;自 Go 1.11 版本引入后&#xff0c;极大地简化了项…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

理想汽车5月交付40856辆,同比增长16.7%

6月1日&#xff0c;理想汽车官方宣布&#xff0c;5月交付新车40856辆&#xff0c;同比增长16.7%。截至2025年5月31日&#xff0c;理想汽车历史累计交付量为1301531辆。 官方表示&#xff0c;理想L系列智能焕新版在5月正式发布&#xff0c;全系产品力有显著的提升&#xff0c;每…...

[KCTF]CORE CrackMe v2.0

这个Reverse比较古老&#xff0c;已经有20多年了&#xff0c;但难度确实不小。 先查壳 upx压缩壳&#xff0c;0.72&#xff0c;废弃版本&#xff0c;工具无法解压。 反正不用IDA进行调试&#xff0c;直接x32dbg中&#xff0c;dump内存&#xff0c;保存后拖入IDA。 这里说一下…...