From 5864e80a88112903d5fea998c90cb6d3fd18b5b3 Mon Sep 17 00:00:00 2001 From: Linloir <3145078758@qq.com> Date: Tue, 13 May 2025 05:39:15 +0000 Subject: [PATCH] Auto deploy pages --- 2019/12/30/summary-2019/index.html | 8 +- 2021/01/11/summary-2020/index.html | 8 +- 2021/12/31/summary-2021/index.html | 8 +- 2022/07/15/os-journal-vol-1/index.html | 8 +- 2022/07/15/os-journal-vol-2/index.html | 8 +- 2022/07/19/os-journal-vol-3/index.html | 8 +- 2022/08/20/os-journal-vol-4/index.html | 8 +- 2022/12/31/summary-2022/index.html | 8 +- 2024/10/11/reborn/index.html | 8 +- 2024/10/12/blog-from-scratch/index.html | 8 +- 2024/10/13/blog-mig/index.html | 8 +- 2024/10/13/host-git-at-home/index.html | 8 +- 2024/10/13/micro-posts/index.html | 8 +- 2024/10/15/tencent-new-start/index.html | 8 +- 2024/10/20/jar-via-adb/index.html | 8 +- 2024/11/08/first-grading/index.html | 8 +- 2024/11/08/linux-commands/index.html | 8 +- .../19/listary-quick-clone-command/index.html | 8 +- .../22/debug-windows-socket-drain/index.html | 8 +- 2024/12/31/summary-2023-2024/index.html | 8 +- 2025/03/17/coroutine-llm-qa/index.html | 8 +- 2025/05/12/swift-state-binding/index.html | 362 ++++++++++++++++++ archives/2019/12/index.html | 10 +- archives/2019/index.html | 10 +- archives/2021/01/index.html | 10 +- archives/2021/12/index.html | 10 +- archives/2021/index.html | 10 +- archives/2022/07/index.html | 10 +- archives/2022/08/index.html | 10 +- archives/2022/12/index.html | 10 +- archives/2022/index.html | 10 +- archives/2024/10/index.html | 10 +- archives/2024/11/index.html | 10 +- archives/2024/12/index.html | 10 +- archives/2024/index.html | 10 +- archives/2024/page/2/index.html | 10 +- archives/2025/03/index.html | 10 +- archives/2025/05/index.html | 347 +++++++++++++++++ archives/2025/index.html | 10 +- archives/index.html | 10 +- archives/page/2/index.html | 10 +- archives/page/3/index.html | 10 +- categories/index.html | 12 +- categories/技术/index.html | 10 +- categories/技术/page/2/index.html | 10 +- categories/杂思/index.html | 10 +- index.html | 10 +- links/index.html | 14 +- page/2/index.html | 10 +- page/3/index.html | 10 +- tags/Swift/index.html | 347 +++++++++++++++++ tags/iOS/index.html | 347 +++++++++++++++++ tags/index.html | 12 +- tags/linux/index.html | 10 +- tags/博客/index.html | 10 +- tags/后端/index.html | 10 +- tags/大学/index.html | 10 +- tags/奇技淫巧/index.html | 10 +- tags/安卓/index.html | 10 +- tags/工作/index.html | 10 +- tags/年终总结/index.html | 10 +- tags/开发/index.html | 10 +- tags/操作系统/index.html | 10 +- tags/瞎捣鼓/index.html | 10 +- tags/短文/index.html | 10 +- tags/综合/index.html | 10 +- tags/编程语言/index.html | 10 +- tags/自言自语/index.html | 10 +- tags/运维/index.html | 10 +- tags/长更/index.html | 10 +- tags/问题定位/index.html | 10 +- 71 files changed, 1721 insertions(+), 318 deletions(-) create mode 100644 2025/05/12/swift-state-binding/index.html create mode 100644 archives/2025/05/index.html create mode 100644 tags/Swift/index.html create mode 100644 tags/iOS/index.html diff --git a/2019/12/30/summary-2019/index.html b/2019/12/30/summary-2019/index.html index 648c42a..2c32dc6 100644 --- a/2019/12/30/summary-2019/index.html +++ b/2019/12/30/summary-2019/index.html @@ -7,7 +7,7 @@ - + @@ -166,7 +166,7 @@ isHome: false, isHighlightShrink: false, isToc: false, - postUpdate: '2025-03-17 21:25:21' + postUpdate: '2025-05-13 13:38:52' }

年终总结 - 2019

  还有24h,2019就结束了
  本来想说,今年是过去17年中最糟糕的一年
  但仔细想想,大概之后的每一年都会是这样,没什么意思,所以也不想写很多情绪化的东西,就随便说说好了。
  
  我想,这一年我学到的唯一的道理,就是
  “在学校之外的很多事情,自有他们发展的规律。有很多事情,努力除了能让自己不后悔以外,什么也改变不了。”
  
  今年第一次真正认识到人的渺小,在意外、灾难、疾病面前,人的力量是薄弱的,甚至,连一点挣扎的机会都没有。在无锡侧翻的高架桥下的人也许永远也料不到自己会被180吨的轧钢要去了性命,重庆广场305楼下的两名学生也绝不会想到自己会因为一具没了灵魂的躯壳而永远停留在17岁。就像任何人都无法躲避死亡,我们所有的观念,行为无非是在改变着我们走向终点的路途罢了。
  
  我自己的经历也不例外。我以为自己可以做到,我以为只要我倾注足够的精力,我祈祷,我等待,事情就可以有所改变,甚至还凭着侥幸心理还在知乎上写了一篇回答,给别人讲方法,提帮助。
  就像在用沙子搭积木,一粒一粒地把沙子垒起来,注水,看它们黏在一起,即便我知道当水全部蒸发的时候,所有的努力都会化为泡影,但我不信这个邪,我骗自己,只要我不断地修补、维护,水就永远不会蒸干,于是一眨眼便是三年。
  但突然有一天,一阵风吹过,带走了不起眼角落里最后一滴水,什么也没有了。
  
  曾经看过一个理论,在高维的空间里,时间像长、宽、深那样是既定的,也就是说我们现在经历的,过去发生的,和即将发生的一切,都是存在的。
  我想了很久,难道这不就意味着混吃等死吗?
  也还是有一些差别的。对于处于三维的我们,未来之所以是未来,正是因为它的不可预见性,就像看不到的立方体的背面那样。即使我能猜到它背面的样子,即使翻转它不会对它有一分一毫的改变,但我仍然对它抱有好奇,好奇和我想象的有什么差别。
  努力也许改变不了结果,但努力的过程会创造回忆。
  站在2019的终点看之前的365个日夜,有开心,有难过,有绝望。我看到自己因为一句话而高兴,又因为一些事而失落;我看到自己疯癫的样子,也看到自己沉默的样子;我看到一些人因为我而高兴,也看到一些人被我波动的情绪所影响…所有的这一切构筑了我来到这世界第17年的回忆,我的2019年。
  “如果我什么也改变不了,那我就在这个世界里创造一些回忆吧。”
  (正文完)
  
  P.S.过去的一年因为自己的原因情绪波动很大,很多时候都因为失控没有去注意正常的情绪表达,多多少少都对身边的人产生了影响。借此机会,我希望向很多人道歉,真的对不起。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2019/12/30/summary-2019/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

年终总结 - 2019

  还有24h,2019就结束了
  本来想说,今年是过去17年中最糟糕的一年
  但仔细想想,大概之后的每一年都会是这样,没什么意思,所以也不想写很多情绪化的东西,就随便说说好了。
  
  我想,这一年我学到的唯一的道理,就是
  “在学校之外的很多事情,自有他们发展的规律。有很多事情,努力除了能让自己不后悔以外,什么也改变不了。”
  
  今年第一次真正认识到人的渺小,在意外、灾难、疾病面前,人的力量是薄弱的,甚至,连一点挣扎的机会都没有。在无锡侧翻的高架桥下的人也许永远也料不到自己会被180吨的轧钢要去了性命,重庆广场305楼下的两名学生也绝不会想到自己会因为一具没了灵魂的躯壳而永远停留在17岁。就像任何人都无法躲避死亡,我们所有的观念,行为无非是在改变着我们走向终点的路途罢了。
  
  我自己的经历也不例外。我以为自己可以做到,我以为只要我倾注足够的精力,我祈祷,我等待,事情就可以有所改变,甚至还凭着侥幸心理还在知乎上写了一篇回答,给别人讲方法,提帮助。
  就像在用沙子搭积木,一粒一粒地把沙子垒起来,注水,看它们黏在一起,即便我知道当水全部蒸发的时候,所有的努力都会化为泡影,但我不信这个邪,我骗自己,只要我不断地修补、维护,水就永远不会蒸干,于是一眨眼便是三年。
  但突然有一天,一阵风吹过,带走了不起眼角落里最后一滴水,什么也没有了。
  
  曾经看过一个理论,在高维的空间里,时间像长、宽、深那样是既定的,也就是说我们现在经历的,过去发生的,和即将发生的一切,都是存在的。
  我想了很久,难道这不就意味着混吃等死吗?
  也还是有一些差别的。对于处于三维的我们,未来之所以是未来,正是因为它的不可预见性,就像看不到的立方体的背面那样。即使我能猜到它背面的样子,即使翻转它不会对它有一分一毫的改变,但我仍然对它抱有好奇,好奇和我想象的有什么差别。
  努力也许改变不了结果,但努力的过程会创造回忆。
  站在2019的终点看之前的365个日夜,有开心,有难过,有绝望。我看到自己因为一句话而高兴,又因为一些事而失落;我看到自己疯癫的样子,也看到自己沉默的样子;我看到一些人因为我而高兴,也看到一些人被我波动的情绪所影响…所有的这一切构筑了我来到这世界第17年的回忆,我的2019年。
  “如果我什么也改变不了,那我就在这个世界里创造一些回忆吧。”
  (正文完)
  
  P.S.过去的一年因为自己的原因情绪波动很大,很多时候都因为失控没有去注意正常的情绪表达,多多少少都对身边的人产生了影响。借此机会,我希望向很多人道歉,真的对不起。

+
文章作者: Linloir
文章链接: https://blog.linloir.cn/2019/12/30/summary-2019/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

年终总结 - 2020

准切地说,这篇年终总结来得有些晚了,晚了一个月十一天二十三小时五十九分钟。但过去的这一年是那么的不可思议,那么的跌宕起伏、刻骨铭心,倘若能用一篇年终总结给这样的一年画上一个句号,便是再好不过的了。

+

年终总结 - 2020

准切地说,这篇年终总结来得有些晚了,晚了一个月十一天二十三小时五十九分钟。但过去的这一年是那么的不可思议,那么的跌宕起伏、刻骨铭心,倘若能用一篇年终总结给这样的一年画上一个句号,便是再好不过的了。

公元贰零贰零年,我来到这个世界的第十八年。年初,武汉疫情爆发,所有的一切都仿佛按下了暂停键,电影取消了,商场关闭了,学校放假了,就连那么多年来从未改变的高考时间也史无前例地推迟了。在这些与自己独处的漫长日夜里,很难得地,我慢慢开始和自己交流,和过去交流,执念被慢慢放下,伤痕开始逐渐愈合,记忆的回声终于不再萦绕,一切都在一个梦醒的早晨恢复正轨。年中,高考是生活赠与我的第一个成人礼,高考结束后的第二天,我结束了一个人面对生活的日子,我有了陪伴我、鼓励我、支持我、给我惊喜的女朋友,我收获了让我感到温暖而幸福的爱情,这是生活赠与我的第二个成人礼。第三个成人礼,是中大录取的通知讯息。当我看到短信的时候,我想到了过去三年我做的所有的事情,我想到了高考后的不甘,想到了她,想到了未来,我之后所有的生活都在那一刻,因为那一个短信而走向了一个崭新的方向。年末,我来到了大学,遇到了和蔼的老师,友好的舍友,我犹记得每一次和所爱之人见面时那种溢于言表的喜悦与激动,犹记得期末周复习的紧张与担心。而这个学期所有的故事,也都以虽不差但仍不尽如意的期末成绩画上了完整的句号。

过去这一年,我经历了悲伤,感受了快乐,收获了爱情,也开始了我成年后的第一年人生。2019快结束的时候,我认为生活已经不能更糟了,然而,2020开年时便驳倒了我这样的想法。但过完整整一年,虽然生活在很多时候变得更糟了,但在更多的时候,变得更加地与以往不一样了——我们认识到生命的宝贵,看到信仰的光芒与责任的力量,我们开始与身边的人联系起来,我们和家人们一起说话,和朋友散心,这一切,在2020都显得那么不一样。

可以说,从去年开始,我才真正开始生活。

转眼就要离开鼠年,希望我们所有人都能在新的一年,再出发。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2021/01/11/summary-2020/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

年终总结 - 2021

很快啊,又是一年过完了。
不知道什么时候开始,感觉一年的长度开始越来越短,短到年初念叨的想见的人到了年末也还是没有见,短到年初开始背的六级单词到了年末也没背下几个,短到年初那些信誓旦旦在今天看来不过又是明年一定…

+

年终总结 - 2021

很快啊,又是一年过完了。
不知道什么时候开始,感觉一年的长度开始越来越短,短到年初念叨的想见的人到了年末也还是没有见,短到年初开始背的六级单词到了年末也没背下几个,短到年初那些信誓旦旦在今天看来不过又是明年一定…

如果要用一个词来描述2021,我认为“改变”是最贴切不过的。

年初的时候,确诊了反流性食管炎。
本来以为会像以往的胃疼那样不过是短时间生活习惯的影响,过一阵子就会自己康复,但没想到即便是做了胃镜开了药也仍然没有阻止它一直折磨我到今天。为了缓解这个问题对生活的影响,很多习惯都不得不改变,其中就包括戒掉我喝了六七年的奶茶和几乎所有的甜食。
到了年中,就是转专业。
本是父母随心的一问,却没想让本来准备努力保研遥感的我重新思考了转专业的可能性,并在截止日期当天提交了申请。
在转专业的过程中发生了很多其他的事情,并且还要同时准备着转专业失败可能面临的绩点断崖下滑以及忍受每晚胃病的折磨,使得那一个月的每一天都无比难熬。
也正是在这个过程中我改变了对曾经很亲密的人的看法,并最终选择了去和平结束上一段关系。

除了这些明显的生活上的改变以外,今年更多的是一些想法和看法上的改变。

@@ -185,7 +185,7 @@ btf.addGlobalFn('pjaxSend', () => {

今天,过去的一年已成定局,新的一年就在我写下这些文字的时候就已然悄无声息地开始。如果要说对2022有什么展望的话…

我希望,
新的一年,
我和我所爱的所有人,
平安,健康,快乐。
就这样,就够了。

最后,
感谢过去的一年有你们陪伴。
真的,
谢谢你们。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2021/12/31/summary-2021/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

操统实验日志 第一章 序章

简述

+

操统实验日志 第一章 序章

简述

在一切开始之前,请允许我先简要地介绍一下关于这个实验的一切

它是关于什么的

@@ -506,7 +506,7 @@ btf.addGlobalFn('pjaxSend', () => {

目前为止,环境已经基本配置完成了
接下来就让我们开始愉快的操作系统实验之旅吧!

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2022/07/15/os-journal-vol-1/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

操统实验日志 第二章 万丈高楼平地起

关于本章

+

操统实验日志 第二章 万丈高楼平地起

关于本章

本章的将会首先介绍操作系统是如何运行起来的,并在此基础上介绍实现一个完备的操作系统实验需要实现哪些方面,以及这些部分的先后顺序和依赖关系

由于这份文档我并不打算作为一份完备的教程文档来编写,因此语言方面的介绍会相对简略或是跳过,对应的详细介绍可以参考学校的同步教程

在本章的后半部分,将会介绍MBR和中断的相关知识,记录如何编写MBR、测试使用BIOS启动MBR引导程序并通过中断输出字符串进行测试

@@ -953,7 +953,7 @@ BIOS从0x7C00处开始执行代码,其并不区分内存中存储 下一章中,将会编写bootloader,从mbr中加载bootloader并且启动,最后在bootloader中让CPU进入保护模式
如果准备好了的话,就让我们进入下一章吧!

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2022/07/15/os-journal-vol-2/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me
最新文章

操统实验日志 第三章 从实模式到保护模式

关于本章

+

操统实验日志 第三章 从实模式到保护模式

关于本章

在本章的第一部分中,将会介绍读取硬盘的CHS方式、LBA方式以及如何通过inout指令读写硬盘,之后会将上一章输出Hello World!的代码移植到BootLoader中,并且从MBR中加载并跳转到编写的BootLoader执行

第二部分中,会回顾保护模式的概念并介绍进入保护模式的四个步骤,并在开启保护模式之后输出第二个Hello World

第一次跃进:从MBR跳转到BootLoader

@@ -970,7 +970,7 @@ LoopCount &= SectorCount \times 512 \div 2 \\

完成
至此,就完成了本章的全部任务,赶紧使用make clean build run来测试代码的运行情况吧!

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2022/07/19/os-journal-vol-3/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

操统实验日志 第四章 勇者之路

关于本章

+

操统实验日志 第四章 勇者之路

关于本章

在本章节的第一部分中,将会简要介绍在下一章中将要编写的KernelLoader,以及在开始着手进行它的编写之前所需要完成的,包括各种驱动、文件系统接口等在内的诸多准备工作。

在第一部分之后,我决定按照KernelLoader中的函数调用顺序,逐节完成KernelLoader中所需要的所有准备工作,因此在第二部分中,将会首先记录如何在项目中使用C语言和汇编混合编程,包括C语言是如何进行函数调用的,以及内联汇编中NASM向AT&T迁移语法所需要注意的问题。有了这部分基础知识,就可以进行第三部分编写一些常用的驱动,并从我个人的角度讲讲为什么要这么做,它对后续的代码编写能够起到哪些帮助。

在之后的第四部分中,会进行有关文件系统的知识的详述,并且带领大家阅读微软关于FAT文件系统的文档,根据文档完成FAT文件系统接口的设计和实现。

@@ -1845,7 +1845,7 @@ VirtualPageIndex &= VirtualPageAddress >> n \nonumber \\

勇者奖章
恭喜你,读完了所有日志中最长最复杂的一篇,后面的实验之路将会因这一章的努力而愈发平坦。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2022/08/20/os-journal-vol-4/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

年终总结 - 2022

2022.12.31 21:00
今年只剩下一场电影的时间了。

+

年终总结 - 2022

2022.12.31 21:00
今年只剩下一场电影的时间了。

过去一年,如果要用一个词语概括的话,那我想应当是“遇见”吧。

其实,关于这个词语,在过去的一年里的无数个瞬间,我都有过构想。
之所以选择“遇见”,因为遇见有着往前走的意思,当我们没有再停留在原地的时候,当我们不在回头看的时候,才会看见那些原本看不见的风景,遇见那些原本碰不到的人们。

过去的一年里,我确实有在向前走,如果更加贴切一些地说,应当是在向前狂奔。
年初的时候,我终于决定选择试着加入Matrix的大家庭,这个决定成为了我今年做得最正确的决定之一。在Matrix,我遇见了真正优秀,有梦想和追求的人们,我看到了与宿舍舍友待白昼如黑夜迥然不同的生活态度,我开始寻着前辈的步子,发展自己热爱的方向,向着自己曾经最仰慕的样子进步。
接着,我遇见了一个温柔,耐心而又体贴的女生。最初的遇见,本以为只会是寥寥几语就会最终沉没在微信记录中的一面之缘,但完全出乎意料地,这一面之缘让我们互相都成为了对方生命中最重要的人之一。这一次遇见,不但让我两点一线的生活再一次有了色彩,更是给过去的一年里留下了无数令我难忘的回忆。
在今年的五月份,我还在知乎收到了一份很长的留言,留言那头是我的初恋,留言是关于我曾经的一篇有关她的知乎回答。在我们分手后的很长一段时间里,那篇回答都是被我删除的状态,直到今年三月份的时候,我决定正视和放下我的过去,于是恢复了那一篇回答,她看到了,特地来感谢我。留言里讲述了一些分手以后的事情和她的近况,她也有了新的生活,新的恋人,希望我不要再因为过去而责怪自己。读完留言是泪流满面,三年过去了,大家都没选择憎恨对方,都没有留在原地,而是都踏入了新的环境,新的生活。
再后来,我搬到了D502,在那里遇见了后半年玩的最多的一只吉祥物,开启了接下来几乎大半年的实验室生活。D502可以说见证了我过去大半年的脚步,见证了我许多个难忘的项目,我的操作系统、计网小作业和我的图形学大作业等等等等。

@@ -185,7 +185,7 @@ btf.addGlobalFn('pjaxSend', () => {

感谢2022带给我的成长,回忆。

……

接下来,把时间交给2023,我们拭目以待。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2022/12/31/summary-2022/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

重生

时隔两年,终于借着重新配置家里网络环境的契机,重新搭建了这个博客。

+

重生

时隔两年,终于借着重新配置家里网络环境的契机,重新搭建了这个博客。

原先关于操作系统的文章正在慢慢搬迁,应该很快就能恢复了~

再一次启用关于自己的博客,感觉心里良多感慨。还记得上一次搭博客时的自己,刚来到计算机学院,对着网上的保姆教程在腾讯云的小机器上搭了 git 仓库、配置了宝塔面板、DNS 解析。

那时的自己对 TLS、证书、Git、反代、CDN、Docker 这些东西都还是那么陌生,以至于教程之外的东西完全不敢去碰,哪怕是在宝塔面板上配一个 Let’s Encrypt 的证书都要折腾好久,也没有去研究 hexo deploy 到底 deploy 了什么到服务端,只觉得能跑便是好事,这也就导致了后来的删库跑路事件——本地的博客仓库被主动删除,等到发现服务器上是没有 Markdown 源文件的时候已经太迟,由于没有了源文件,写新的博客势必会导致旧的 html 被覆盖,又因为文章实在太长迟迟没有动手迁移,原先的数万字长文就这样被冻在了旧的博客里长达两年。

@@ -182,7 +182,7 @@ btf.addGlobalFn('pjaxSend', () => {

不夸张地说,看到熟悉的页面再一次出现在浏览器中的时候,内心有许多感慨,大概就像离家的游子多年后重新推开家门时那样吧。拂去把手上的灰尘,推开门回到曾经熟悉的地方,所有的东西都还在原本的地方等着自己,仿佛从来没有离开过那样。博客大概就是我内心无处安放的杂思的归宿吧,我想,如今它们终于又能安家了。

这一次回来,不知道能够持续多久,但我希望,能够长一些、再长一些。至于内容,我也不打算维持早年纯技术的导向了,我更多地想让这个博客成为我存在的痕迹,让多年后的自己看到曾今的文章能够会想起当年的纠结、焦虑、喜悦或是激动,能够从这里,看到我。

总之,欢迎回家。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/11/reborn/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

基于 IPv6 公网地址、NAS 和 MacMini 的私有部署博客方案

方案速览

简单来说,方案分为了几个主要的部分:

+

基于 IPv6 公网地址、NAS 和 MacMini 的私有部署博客方案

方案速览

简单来说,方案分为了几个主要的部分:

  1. 根据 在 NAS 上部署自己的 Gitea 服务,无需公网服务器 方案打通外网到家用 NAS / MacMini 的链路
  2. 采用 Git 仓库 main 分支存放源码 + Gitea Actions 编译至 publish 分支实现源码及制品存储
  3. @@ -187,7 +187,7 @@ btf.addGlobalFn('pjaxSend', () => {

    环境准备

    在配博客之前,我是先配好了 Nas 上的 Gitea 服务,可以参考 在 NAS 上部署自己的 Gitea 服务,无需公网服务器 这一篇博客来准备基本的网络环境和 Gitea 服务。

    (也就是说,我是先搭好了 Gitea,然后实在不知道能拿干点什么,才决定把博客迁移回来的。有点为了醋包饺子的感觉哈哈,不过现在博客全部内容都运行在自己本地感觉还是颇有成就感的)

    仓库配置

    待后面补充~

    -
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/12/blog-from-scratch/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

短文 - 博客迁移小记

最开始想的迁移方案是使用 skip-render 标记 html,但始终觉得不够优雅,因为导航栏、个人信息、头图之类的内容时常都会变,如果 skip-render 那永远都会是当时那个版本的页面,甚至可能超链接都是失效的,除了能显示原本的博文之外其实体验应该是相当差的——横竖感觉就是很突兀嘛!

+

短文 - 博客迁移小记

最开始想的迁移方案是使用 skip-render 标记 html,但始终觉得不够优雅,因为导航栏、个人信息、头图之类的内容时常都会变,如果 skip-render 那永远都会是当时那个版本的页面,甚至可能超链接都是失效的,除了能显示原本的博文之外其实体验应该是相当差的——横竖感觉就是很突兀嘛!

直到今天突然意识到,hexo 渲染 markdown 为 html 文本肯定会分为三个大部分:

  1. 正文前部的各种元素,例如头图、导航栏、侧边栏等
  2. @@ -192,7 +192,7 @@ btf.addGlobalFn('pjaxSend', () => {

    然后再把原先的图片复制到现在的 img 目录下,批量改一手路径,Done!

    谁能想到这个卡了我两年的问题,竟然能 15 分钟就搞定了!!!

    过于激动,遂特写此文记录一下,真是拍大腿啊!!!

    -
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/13/blog-mig/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

在 NAS 上部署自己的 Gitea 服务,无需公网服务器

方案速览

简单来说,方案包含了以下几个主要部分:

+

在 NAS 上部署自己的 Gitea 服务,无需公网服务器

方案速览

简单来说,方案包含了以下几个主要部分:

  1. 公网访问使用光猫桥接路由器拨号,通过路由器同时获取 IPv4 大内网和 IPv6 公网 /64 地址
  2. DNS 解析通过 MacMini 上部署的 ddns-go 实现
  3. @@ -248,7 +248,7 @@ btf.addGlobalFn('pjaxSend', () => {

    不过,由于 Cloudflare 只支持有限的端口转发,并且只支持基于 http/https 协议的流量转发,因此适用面相对不那么广,但是家用部署网站服务还是绰绰有余了。具体允许的端口号见 Cloudflare 文档

    经过测试,中国联通封了 80,443,2096 端口,回源我采用的 2095 端口,这个在 Cloudflare 控制台 - 规则 - Origin Rules 可以创建回源规则针对特定域名指定。

    Gitea 安装与反向代理

    待后续翔实~

    -
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/13/host-git-at-home/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

短文 - 关于短博文的碎碎念

感觉如果博客只写长文的话,好像很快就会疲乏,其实很多时候想说的内容就是一两句话,即便硬是写成了长文,又觉得好像啰嗦了。

+

短文 - 关于短博文的碎碎念

感觉如果博客只写长文的话,好像很快就会疲乏,其实很多时候想说的内容就是一两句话,即便硬是写成了长文,又觉得好像啰嗦了。

看到 Hexo - Butterfly 有提供一个 “说说” 的页面可以用 .yml 格式来存一些说说文档,但是仔细一看发现好像不会自动分页,这样一来图片一多感觉加载就会变成彻底的灾难…

不知道为什么在静态编译的时候没有做成本地分页的格式呢… 就像文章那样,其实在编译阶段就可以分散到不同的 index.html 去了,好可惜,也许以后有空会想办法看看能不能改吧…

还有很多云存储的方案,但感觉把自己的内容放在云上,总感觉会比较担心数据安全和以后的迁移成本,纯本地的话哪怕一天发两条十年也不过才不到上万条数据,一个 .yml 就带走了,哎可惜没分页终究还是不打算去用。

想来想去,就把短博客也当作正常的文章一样的显示在主页吧,不过会在标题前面加上 “短文” 的标记和对应的 tag,也方便浏览的时候来做区分好了

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/13/micro-posts/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

短文 - 转正日

今天收到了转正邮件,正式标志着一个新的人生阶段的开始。

+

短文 - 转正日

今天收到了转正邮件,正式标志着一个新的人生阶段的开始。

对自己的期望就是,不要忘记做技术的初心,在新的阶段能有所成长,有所收获。

Po 一张在鹅厂的第一个关爱里程碑~

first_day

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/15/tencent-new-start/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

用 adb + app_process 执行 Java 代码 —— 一种无需安装 apk 的脱机代码执行方案

方案速览

本方案本质上是使用了安卓提供的 app_process 命令,在将 Java 代码正确地打包为需要的 .jar 或是 .dex 文件后,通过 app_process 启动对应的入口函数来实现 adb 执行 Java 代码的能力。

+

用 adb + app_process 执行 Java 代码 —— 一种无需安装 apk 的脱机代码执行方案

方案速览

本方案本质上是使用了安卓提供的 app_process 命令,在将 Java 代码正确地打包为需要的 .jar 或是 .dex 文件后,通过 app_process 启动对应的入口函数来实现 adb 执行 Java 代码的能力。

对于目标 .jar 或是 .dex 文件,有两种不同的编译方案:

  1. .dex 文件方式:
      @@ -272,7 +272,7 @@ btf.addGlobalFn('pjaxSend', () => {
    1. 在研究 atx/uiautomator2 的实现的时候,先入为主地就认为作者使用了 uiautomator <jar> 这种方式调用,后面注意力都放在了查找作者针对 u2.jar 的打包方式和相关代码上了,以至于在仓库里搜索 u2.jar 的时候竟然没有注意到在搜索结果中 core.py 赫然有着 command = "CLASSPATH=/data/local/tmp/u2.jar app_process / com.wetest.uia2.Main" 这一启动方式,与答案擦肩而过并且进一步在寻找 uiautomator 1.0 的打包方式上浪费了大半天的时间
    2. 对于一个陌生的仓库,如果想要了解它的源码实现,不一定非要自己去读,除了进行仓库里的关键词搜索,也可以去查找别人的源码解析,走个捷径
    -
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/10/20/jar-via-adb/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

短文 - 面对首次绩效考核的一些随笔

快要到年底绩效考核的时间了,回想过去半年好像一直忙忙碌碌但好像又没有什么很亮眼的成果。期间还有一大部分精力都投在了一个设计难度远大于实现难度的需求。

+

短文 - 面对首次绩效考核的一些随笔

快要到年底绩效考核的时间了,回想过去半年好像一直忙忙碌碌但好像又没有什么很亮眼的成果。期间还有一大部分精力都投在了一个设计难度远大于实现难度的需求。

回过头想想,其实在工作上开始做一件长期的事情之前,还是要去评估可行性、投入以及收效,到底这件事情有多大的优先级,是不是就值得现在立马开始投入人力去做这个。到底做些什么可以被业务感知到,从而去判断,到底哪些需求才是重要的,而不是一味的承接需求,最后反倒抓不到重点了。

当然,除此之外,更重要的一点是,在知道了公司存在强制的 Underperform 比例时,不免会想,也许有一天我也要成为背这个绩效的人?在这种场景下,是否不要把鸡蛋放在一个篮子里更为安全?诚然,上班本质还是一种利益交换,我给公司提供我能够产出的内容,帮助公司节省人力开支或是做原本人力做不了的事情,公司给我反馈大厂背景、经验、人脉和钱,当然,这里面必然伴随着剩余价值的剥削云云,但总的来看,也算是目前相对公平且不错的买卖,在这样的背景下,我还是会在工作的时候专注于需求本身,坚守住技术人应有的底线,但在工作时间之外,确实应该更加关注自身的投资,也许是身体的健康,也许是产品思维,也许真的去做一些能代表自己实力的东西吧。

前几天有看到一个帖子,个人认为说的其实很有道理,大致意思就是,人总要有一些能证明自己能力的东西,在校招的时候,学历就是最大的背书;在工作的时候,便是绩效和公司、项目经历。但是,如果能有足够的其他履历,比如大的开源项目、成功的产品,这些就会替代前者变成能力的证明,毕竟,选择前者只是没有后者的无奈之举。所以,我想,做自己感兴趣的事,并且在这方面出彩,大概才是最有价值的投资吧。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/11/08/first-grading/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me

长更 - Linux 常用指令

先挖坑,慢慢填

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/11/08/linux-commands/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

长更 - Linux 常用指令

先挖坑,慢慢填

+
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/11/08/linux-commands/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

Listary 命令分享 - 快捷 clone 仓库并使用 VSCode 打开

背景

日常工作中,经常会需要临时 Clone 某个仓库并且用 VSCode 打开,在 Windows 上我一般都是:

+

Listary 命令分享 - 快捷 clone 仓库并使用 VSCode 打开

背景

日常工作中,经常会需要临时 Clone 某个仓库并且用 VSCode 打开,在 Windows 上我一般都是:

  1. 用文件资源管理器定位到需要 Clone 到的位置然后右键呼出终端
  2. git clone
  3. @@ -198,7 +198,7 @@ btf.addGlobalFn('pjaxSend', () => {

    之后,在文件夹中直接输入 clode <repo url> [dest folder] 即可一键 clone

    [dest folder] 为选填,不填则是默认取 <repo url> 末尾仓库名称作为目标文件夹,同直接执行 git clone <repo url> 行为保持一致

    Settings

    -
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/11/19/listary-quick-clone-command/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

问题定位回顾 - Windows 上发起 tcp 连接时提示 Only one usage of each socket address (protocol/network address/port) is normally permitted

问题背景

某天在 Windows 宿主机上执行任务时,发现 wda 指令请求一直失败,查看日志发现唯一有效的错误日志是 Only one usage of each socket address (protocol/network address/port) is normally permitted,回顾宿主机环境在过去一段时间没有进行过变更,并且该问题是第一次出现,此前相同环境并没有出现过这个问题

+

问题定位回顾 - Windows 上发起 tcp 连接时提示 Only one usage of each socket address (protocol/network address/port) is normally permitted

问题背景

某天在 Windows 宿主机上执行任务时,发现 wda 指令请求一直失败,查看日志发现唯一有效的错误日志是 Only one usage of each socket address (protocol/network address/port) is normally permitted,回顾宿主机环境在过去一段时间没有进行过变更,并且该问题是第一次出现,此前相同环境并没有出现过这个问题

尝试在其他宿主机以及本地开发机上执行相同命令均不能稳定复现该问题,其中 Linux 开发机无法复现该问题

error info

定位过程

报错分析

由于报错信息只有一行,也只能从这个信息来入手。搜索引擎检索得到如下内容:

@@ -280,7 +280,7 @@ btf.addGlobalFn('pjaxSend', () => {

此处额外解释一下第二点中为什么又可以直接从容器内访问 usbmuxd 了:前面发现容器内请求 host.docker.internal 会让 docker 以 com.docker.backend.exe 的身份使用 127.0.0.1 发起一个代理的请求,这还正好满足了 usbmuxd 只监听 127.0.0.1:27015 的行为了,这样宿主机的反代服务也就不需要了。

对于 Linux 服务,如果需要保持架构上的统一,一个可能的优化方向是将 usbmuxd 监听的 socket 映射到容器内?考虑到 docker daemon 的 socket 可以做到,大概这个方向也可行,但目前还没有做尝试,就留作一些可行的方案放在此处吧~

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/11/22/debug-windows-socket-drain/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

年终总结 - 2023 至 2024

是因为太久没有写过叙事风格的文字,还是因为脑子早已经被快节奏的短视频侵蚀,又到了年末回顾的时候,我竟与面前的电脑周旋了一晚,最后愣是一句能读的话都没有写出来。末了,把写不出东西这个毛病归结于家里的环境缺乏情调,次日专门找了个海边的图书馆来写,结果到了太阳都下山了,才想起来自己此行的正事不是来这儿看书,而是写点什么。倒是歪打正着,好不容易来一趟,总得在关门之前写下点什么,遂匆匆留下此篇,作为我过去两年存在过的痕迹。

+

年终总结 - 2023 至 2024

是因为太久没有写过叙事风格的文字,还是因为脑子早已经被快节奏的短视频侵蚀,又到了年末回顾的时候,我竟与面前的电脑周旋了一晚,最后愣是一句能读的话都没有写出来。末了,把写不出东西这个毛病归结于家里的环境缺乏情调,次日专门找了个海边的图书馆来写,结果到了太阳都下山了,才想起来自己此行的正事不是来这儿看书,而是写点什么。倒是歪打正着,好不容易来一趟,总得在关门之前写下点什么,遂匆匆留下此篇,作为我过去两年存在过的痕迹。

2024 年的终曲轻轻落幕,与我二十一和二十二岁的许多事情一样,没有轰轰烈烈的收场,只是在那某一瞬间突然意识到,过去的时光就这么结束了。

是什么时候开始觉得时间过得很快的呢?
是那一天想喝家门口的喜茶,却发现它几个月前就已经搬走的时候吗?
是那个实习结束后的早晨伸着懒腰起床,打开手机看见日历上赫然写着 10 月的时候?
是考完研的那天午后,抱着沉沉的资料最后一次走出图书馆的瞬间?
是意识到自考研后又已经过去了两个 75 天的那天?
还是一转眼发现就连 2024 都已经过完的今天?

已经记不太清了。
只觉得像是一个阳光灿烂的下午,躺在阳台上被太阳晒得暖暖的椅子里眯上了眼睛。在梦里,时间很慢,慢到周一到周五的时间像有一个学期那么长,床头的耳塞堆成了小山,书页翻得泛黄。醒来的时候,冬日的阳光还照在脸上,窗外的鸟儿还在叽喳,楼下的商铺喇叭还播着广告,对面小区的女人也还在遛她的狗,一切都好像没变。只是家里客厅的台历不再写着 2023,楼下不再有开了两年的排骨饭,对面小区的萨摩也再没看到了。

@@ -194,7 +194,7 @@ btf.addGlobalFn('pjaxSend', () => {

那,选择另一条路,就会更好吗?

我永远也不会知道,在平行世界里,选择另一条路的自己,到底会不会过得更好。但可以肯定的是,在往后的日子里,在现在的道路上,我会好好过。

2025,向前走,别回头。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2024/12/31/summary-2023-2024/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕

Coroutine 相关疑惑大模型问答记录

近日在看 python 的 asyncio 时突然想起了曾经对 C++ coroutine 以及 go 的 goroutine 的诸多未解疑惑。还记得当时有这些疑惑的时候,还没有 ChatGPT 或是 DeepSeek 这样方便的大模型解惑,反复查找各种资料最后因为时间原因还是没有深究,而如今 DeepSeek 已然如此发达,遂借此机会解答遗留在心中多年的疑惑,并以此贴记录。

+

Coroutine 相关疑惑大模型问答记录

近日在看 python 的 asyncio 时突然想起了曾经对 C++ coroutine 以及 go 的 goroutine 的诸多未解疑惑。还记得当时有这些疑惑的时候,还没有 ChatGPT 或是 DeepSeek 这样方便的大模型解惑,反复查找各种资料最后因为时间原因还是没有深究,而如今 DeepSeek 已然如此发达,遂借此机会解答遗留在心中多年的疑惑,并以此贴记录。

Round 1

Q:
AsyncIO 或者说,Coroutine 是怎么实现,例如在 await 一个网络请求的时候,进程不会被内核挂起进入等待状态,而是可以继续正常被调度并且执行余下内容的?同时,当网络请求完成的时候,内核又是怎么让进程知道请求完成从而继续 await 后续未执行的内容的

A:

@@ -685,7 +685,7 @@ C --> D[事件循环继续运行其他协程]

两种模型各有优劣,现代运行时(如.NET)甚至支持混合模式,开发者应根据具体需求选择最合适的协程实现。

-
文章作者: Linloir
文章链接: https://blog.linloir.cn/2025/03/17/coroutine-llm-qa/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me
目录
  1. 1. Round 1
    1. 1.1. 一、核心机制
    2. 1.2. 二、内核交互细节
    3. 1.3. 三、性能关键指标
    4. 1.4. 四、操作系统支持
    5. 1.5. 五、编程模型对比
    6. 1.6. 六、典型工作流程
  2. 2. Round 2
    1. 2.1. 一、栈帧保存的必要性
    2. 2.2. 二、栈帧保存的实现方式
      1. 2.2.1. 1. 轻量级方案(Python等解释型语言)
      2. 2.2.2. 2. 高性能方案(C/C++/Rust)
      3. 2.2.3. 3. 零拷贝方案(Go goroutine)
    3. 2.3. 三、栈帧保存的底层原理
      1. 2.3.1. 1. 寄存器级保存
      2. 2.3.2. 2. 栈内存管理
      3. 2.3.3. 3. 栈溢出防护
    4. 2.4. 四、不同语言的实现对比
    5. 2.5. 五、特殊场景处理
    6. 2.6. 结论
  3. 3. Round 3
    1. 3.1. 一、场景还原与问题本质
    2. 3.2. 二、两种核心实现策略
      1. 3.2.1. 1. 共享栈模式 (Stackful Coroutines)
      2. 3.2.2. 2. 状态机模式 (Stackless Coroutines)
    3. 3.3. 三、关键问题解答
      1. 3.3.1. Q1:为何不会发生栈数据覆盖?
      2. 3.3.2. Q2:栈数据是否需要显式拷贝?
      3. 3.3.3. Q3:性能影响对比
    4. 3.4. 四、具体语言实现剖析
      1. 3.4.1. 1. Python AsyncIO
      2. 3.4.2. 2. Rust async/await
    5. 3.5. 五、实际内存布局示例
      1. 3.5.1. 场景:A → B → post_http_request挂起
    6. 3.6. 六、总结
  4. 4. Round 4
    1. 4.1. 一、共享栈协程 (Stackful Coroutines)
      1. 4.1.1. 1. 栈空间管理
      2. 4.1.2. 2. 栈指针切换
      3. 4.1.3. 3. 调用链示例
    2. 4.2. 二、无栈协程 (Stackless Coroutines)
      1. 4.2.1. 1. 实现原理
      2. 4.2.2. 2. 内存布局
      3. 4.2.3. 3. 性能对比
    3. 4.3. 三、关键问题解答
      1. 4.3.1. Q1:协程调用是否需要切换栈指针?
      2. 4.3.2. Q2:如何避免栈数据覆盖?
      3. 4.3.3. Q3:为何无栈协程性能更高?
    4. 4.4. 四、语言实现对比
      1. 4.4.1. 1. Go (共享栈)
      2. 4.4.2. 2. Rust (无栈)
      3. 4.4.3. 3. Python (生成器式无栈)
    5. 4.5. 五、总结
最新文章
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me
目录
  1. 1. Round 1
    1. 1.1. 一、核心机制
    2. 1.2. 二、内核交互细节
    3. 1.3. 三、性能关键指标
    4. 1.4. 四、操作系统支持
    5. 1.5. 五、编程模型对比
    6. 1.6. 六、典型工作流程
  2. 2. Round 2
    1. 2.1. 一、栈帧保存的必要性
    2. 2.2. 二、栈帧保存的实现方式
      1. 2.2.1. 1. 轻量级方案(Python等解释型语言)
      2. 2.2.2. 2. 高性能方案(C/C++/Rust)
      3. 2.2.3. 3. 零拷贝方案(Go goroutine)
    3. 2.3. 三、栈帧保存的底层原理
      1. 2.3.1. 1. 寄存器级保存
      2. 2.3.2. 2. 栈内存管理
      3. 2.3.3. 3. 栈溢出防护
    4. 2.4. 四、不同语言的实现对比
    5. 2.5. 五、特殊场景处理
    6. 2.6. 结论
  3. 3. Round 3
    1. 3.1. 一、场景还原与问题本质
    2. 3.2. 二、两种核心实现策略
      1. 3.2.1. 1. 共享栈模式 (Stackful Coroutines)
      2. 3.2.2. 2. 状态机模式 (Stackless Coroutines)
    3. 3.3. 三、关键问题解答
      1. 3.3.1. Q1:为何不会发生栈数据覆盖?
      2. 3.3.2. Q2:栈数据是否需要显式拷贝?
      3. 3.3.3. Q3:性能影响对比
    4. 3.4. 四、具体语言实现剖析
      1. 3.4.1. 1. Python AsyncIO
      2. 3.4.2. 2. Rust async/await
    5. 3.5. 五、实际内存布局示例
      1. 3.5.1. 场景:A → B → post_http_request挂起
    6. 3.6. 六、总结
  4. 4. Round 4
    1. 4.1. 一、共享栈协程 (Stackful Coroutines)
      1. 4.1.1. 1. 栈空间管理
      2. 4.1.2. 2. 栈指针切换
      3. 4.1.3. 3. 调用链示例
    2. 4.2. 二、无栈协程 (Stackless Coroutines)
      1. 4.2.1. 1. 实现原理
      2. 4.2.2. 2. 内存布局
      3. 4.2.3. 3. 性能对比
    3. 4.3. 三、关键问题解答
      1. 4.3.1. Q1:协程调用是否需要切换栈指针?
      2. 4.3.2. Q2:如何避免栈数据覆盖?
      3. 4.3.3. Q3:为何无栈协程性能更高?
    4. 4.4. 四、语言实现对比
      1. 4.4.1. 1. Go (共享栈)
      2. 4.4.2. 2. Rust (无栈)
      3. 4.4.3. 3. Python (生成器式无栈)
    5. 4.5. 五、总结
最新文章

Swift 学习笔记 - 从 Property Wrapper 视角探索 State 与 Binding 如何工作

背景

基本学完 Swift 语法后,就开始跟随 Apple 关于 Swift UI 的官方教程 来学习 Swift 如何应用在 iOS App 开发中。

+

Driving Changes in your UI with State and Bindings 这一小节中,教程首次引入了 Swift UI 中关于状态的概念。

+

教程中使用了简单的代码来介绍 @State@Binding 属性,以及如何在工程中使用这两个属性:

+
1
2
3
4
5
6
7
8
9
import Foundation

// 省略部分代码 ...
struct RecipeEditorConfig {
var recipe = Recipe.emptyRecipe()
var shouldSaveChanges = false
var isPresented = false
// 省略部分代码 ...
}
+ +
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import SwiftUI


struct ContentListView: View {
// 省略部分代码 ...
@State private var recipeEditorConfig = RecipeEditorConfig()

var body: some View {
// 省略部分代码 ...
RecipeEditor(config: $recipeEditorConfig)
// 省略部分代码 ...
}

// 省略部分代码 ...
}
+ +
1
2
3
4
5
6
7
8
9
10
11
12
13
import SwiftUI

struct RecipeEditor: View {
@Binding var config: RecipeEditorConfig

var body: some View {
NavigationStack {
RecipeEditorForm(config: $config)
// 省略部分代码 ...
}
}
// 省略部分代码 ...
}
+ +

由于之前也接触过其他的前端语言,例如 Dart 或是 JavaScript,自然地就会好奇:Swift 这样的语法设计下,是怎么实现状态的刷新的呢?

+

一些猜测

比较直接的猜测就是,传入的 $config 类似闭包语法,实则是传递了一个 { config in return config } 闭包给 RecipeEditor

+

这看起来好像解答了为什么 RecipeEditor 可以直接修改 ContentListViewrecipeEditorConfig 的值,但实则有几个关键的问题没有解答:

+
    +
  1. @State 存在的意义是在状态变更的时候通知渲染层进行重绘,类似 setState 方法,如果直接传入变量闭包,虽然可以修改,但是如何通知 UI 层重绘?
  2. +
  3. 如果传入的是闭包,闭包是如何赋值给 RecipeEditorConfig 这样的变量的?为什么没有 init 函数依然可以完成这样的赋值?
  4. +
  5. RecipeEditor 中,是可以直接修改 config 的值的,例如直接给 config 赋新值,如果原本的引用通过闭包传入后解析出来赋值给 config,那这样修改后不就丢失了对原先的对象的引用吗?
  6. +
+

几番提问下来,基本可以肯定应该不是直接通过闭包传递的,而是 @State@Binding 做了更复杂的处理

+

而具体做了哪些处理,则要从 Property Wrapper 开始讲起

+

Swift 中的 Property Wrapper

在一篇关于 @State@Binding 的问答中,我了解到,这两个属性并非宏 (至少不是库中按照 Macro 描述编写的那种宏),而是受语言支持的两个 Property Wrapper

+

关于 Property Wrapper 的内容,在 Swift Evolution - Property Wrapper 中有提到整个 Property Wrapper 设计的背景、提案和应用场景

+

简单说来,Property Wrapper 可以分为 3 步:

+
    +
  1. 编写由 @propertyWrapper 标识的结构体,这个结构体用于存储包装属性所需要的所有额外信息以及可以提供的方法(例如一个 lazy 包装属性可能会想要存储当前变量是否已经被初始化过、初始化后的值等),这个结构体会暴露 wrappedValueprojectValue 两个属性供外部访问
  2. +
  3. (猜想): 编译器识别到 @propertyWrapper,将后续结构体对应的 AST 转化为包含该结构体定义的,更复杂的宏定义
  4. +
  5. 编译器识别到 @MyPropertyWrapper,将后续对应的声明 AST 转化为更复杂的表达式,包括一个私有 MyPropertyWrapper<Value> 结构体对象和对应的访问器
  6. +
+

PropertyWrapper 结构体

Property Wrapper 这一方案的提出意图解决的问题就是,当访问一个变量时,能够在不增加越来越多且复杂的编译器属性的同时,支持将通用的、可复用的额外逻辑作用在这个访问过程中

+

例如,关键词 lazy 本质上就是在试图解决这类问题中的一个: 当访问一个变量时,先判断是否初始化,如果初始化则返回初始化后的值,否则进行初始化

+

最初的想法可能就是,写一些重复的代码 (boilerplate code) 来实现这个功能:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Irrelevant code omitted
struct MyClass {
var _myDefaultValue: Int = 123
var _myValue: Int? = nil
var myValue: Int {
get {
if _myValue == nil {
_myValue = _myDefaultValue
}
guard let v = _myvalue else {
raise fatalError()
}
return v
}
set {
_myValue = newValue
}
}
}
+ +

但是如果每一个需要用到这个逻辑的地方都要这么些,未免有些复杂

+

考虑到宏可以扩展代码,也许可以定义一个宏 @Lazy 来展开这些内容,从而避免每次都重复编写

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Irrelevant code omitted
struct MyClass {
// 也就是,将
@Lazy var myValue: Int = 123
// 转换为
var _myValue: Int? = nil
var myValue: Int {
get {
if _myValue == nil {
_myValue = 123
}
guard let v = _myvalue else {
raise fatalError()
}
return v
}
set {
_myValue = newValue
}
}
}
+ +

然而,具体的宏想想就已经非常复杂了

+

也就是说,如果想要直接用宏来实现给属性访问添加额外逻辑这一能力,虽然可以做到,但那样的话似乎更多的关注会在如何实现宏本身而不是实际的逻辑上了 (Make 的困境幻视)

+

那么,从语言设计的角度考虑,是不是可以让开发者更关注于具体逻辑的实现而隐藏宏转换的细节呢?类似 CMake 那样,用一套规范来约束开发者对逻辑的定义,再在这一规范之上构建编译器属性,使得能够将具体逻辑转换成某种编译器能识别的宏,从而开发者只需要遵循规范来定义逻辑,而不再需要编写具体的宏定义了

+

虽然不知道 Swift 具体是怎么实现的,但我想 Property Wrapper 的出现大概率是相似的思路

+

在 Property Wrapper 的描述中,Swift 约定了一个编译器属性 @propertyWrapper,其可以用于修饰自定义的结构体,结构体的一般结构约定如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@propertyWrapper
struct MyPropertyWrapper {
var myPropertyUnderlyValue: MyValueType

init(myPropertyUnderlyValue: MyInitialValueType) {
self.myPropertyUnderlyValue = myPropertyUnderlyValue
}

var wrappedValue: MyValueType {
get {
// Add logic when get
myPropertyUnderlyValue
}
set {
// Add logic when set
myPropertyUnderlyValue = newValue
}
}

var projectedValue: SomeProjectedType {
get {
self
}
set {
self = newValue
}
}
}
+ +

我想,之所以这么设计,是因为通过 struct 可以提供一个统一的抽象语法树节点来描述整个额外逻辑所需要的所有内容。想象如果不使用 struct 结构来包装,那为了实现 @Lazy 的能力,需要找一个地方写 _myValue 变量,另找一个地方写 myValue 需要的 gettersetter 逻辑,并且编译器要能够直到这些分散的表达式节点都是 @Lazy 的一部分,这想想就不好实现

+

通过 struct 的包装,虽然使得实际值的存储多了一层结构体的封装,但简化了编译器的实现,并且也统一了可能的表现形式

+

现在,编译器只需要在将这个结构体转换为一个宏,其在标记了对应属性的声明处进行如下操作即可:

+
    +
  1. 将原先的声明替换为一个 _originalVarName: MyPropertyWrapper 的值
  2. +
  3. 声明 var originalVarName: MyPropertyWrapper { get, set } 访问器,通过 MyPropertyWrapper.wrappedValue 进行访问
  4. +
  5. 声明 var $originalVarName: SomeProjectedType { get, set } 访问器,通过 MyPropertyWrapper.projectedValue 进行访问
  6. +
  7. 生成 synthesized initializer (如果必须)
  8. +
+

看起来就很好实现了,不是吗?

+

projectedValue 和 wrappedValue

State 的魔法

可能的 State 结构体

展开后的 @State 代码

为什么使用 Binding 作为 projectedValue

Binding 的魔法

可能的 Binding 结构体

展开后的 @Binding 代码

文章作者: Linloir
文章链接: https://blog.linloir.cn/2025/05/12/swift-state-binding/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 時痕
\ No newline at end of file diff --git a/archives/2019/12/index.html b/archives/2019/12/index.html index 5fd905b..8c1d548 100644 --- a/archives/2019/12/index.html +++ b/archives/2019/12/index.html @@ -163,7 +163,7 @@ isHome: false, isHighlightShrink: false, isToc: false, - postUpdate: '2025-03-17 21:25:37' + postUpdate: '2025-05-13 13:39:07' }
全部文章 - 1
2019
年终总结 - 2019
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me
最新文章
+
全部文章 - 1
2019
年终总结 - 2019
avatar
Linloir
我、技术、生活与值得分享的一切
Follow Me
最新文章
@@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 1
    2019
    年终总结 - 2019
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 1
    2019
    年终总结 - 2019
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 1
    2021
    年终总结 - 2020
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 1
    2021
    年终总结 - 2020
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 21
    2022
    年终总结 - 2021
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 22
    2022
    年终总结 - 2021
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 1
    2022
    年终总结 - 2021
    2021
    年终总结 - 2020
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 1
    2022
    年终总结 - 2021
    2021
    年终总结 - 2020
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 1
    2022
    操统实验日志 第四章 勇者之路
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 1
    2022
    操统实验日志 第四章 勇者之路
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 21
    2023
    年终总结 - 2022
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 22
    2023
    年终总结 - 2022
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 21
    2025
    年终总结 - 2023 至 2024
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 22
    2025
    年终总结 - 2023 至 2024
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    全部文章 - 1
    2025
    Coroutine 相关疑惑大模型问答记录
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 1
    2025
    Coroutine 相关疑惑大模型问答记录
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    \ No newline at end of file diff --git a/archives/2025/index.html b/archives/2025/index.html index 94e6e38..529a443 100644 --- a/archives/2025/index.html +++ b/archives/2025/index.html @@ -163,7 +163,7 @@ isHome: false, isHighlightShrink: false, isToc: false, - postUpdate: '2025-03-17 21:25:37' + postUpdate: '2025-05-13 13:39:07' }
    全部文章 - 2
    2025
    Coroutine 相关疑惑大模型问答记录
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 21
    2019
    年终总结 - 2019
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    全部文章 - 22
    2021
    年终总结 - 2020
    2019
    年终总结 - 2019
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -192,7 +192,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -230,7 +230,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    +
    avatar
    Linloir
    我、技术、生活与值得分享的一切
    Follow Me
    最新文章
    @@ -190,7 +190,7 @@ btf.addGlobalFn('pjaxSend', () => {
  • 2025 - 2 + 3
  • @@ -228,7 +228,7 @@ btf.addGlobalFn('pjaxSend', () => { 1 -
    网站信息
    文章数目 :
    21
    本站总字数 :
    87.9k
    本站访客数 :
    本站总浏览量 :
    最后更新时间 :