[{"content":"自从上班的地方不给用苹果之后，我就慢慢地将使用环境从苹果中迁移出来， 这篇博客说的是将音乐库从 Apple Music 迁移到 navidrome 中的一些实践。\n需求 智能歌单功能 可以缓存音乐的客户端 可直接扫描音乐文件夹 综上，选择目前能满足我需求而且开发较活跃的 navidrome 。\nnavidrome 安装方面，用 docker compose 启动镜像，配置好之后可以开机启动，只要设置好 docker desktop 的开机启动即可。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 services: navidrome: image: deluan/navidrome:latest container_name: navidrome user: 1000:1000 ports: - \u0026#34;4533:4533\u0026#34; restart: unless-stopped # 自动重启 environment: PUID: 1000 PGID: 1000 TZ: Asia/Shanghai ND_TRANSCODINGENABLED: true volumes: - \u0026#34;/home/ruan/navidrome/config:/data\u0026#34; # 映射配置文件 - \u0026#34;/mnt/g/Music:/music:ro\u0026#34; # 映射音乐库 遇到的问题 alac 无损格式无法播放 之前通过 apple music 无损格式管理音乐库，所以音乐格式是通过m4a容器存储的。 但是 navidrome 的 web 页面和一部分客户端没办法直接播放m4a播放，这一点让我比较烦恼。\n经过询问gpt发现能利用ffmpeg直接将m4a格式转换成flac格式，并且能保留全部标签。\n1 2 3 4 5 6 # 把music.m4a转换成music.flac ffmpeg -i \u0026#34;music.m4a\u0026#34; -c:a flac -compression_level 8 -map 0 -map_metadata 0 \u0026#34;music.flac\u0026#34; # 把当前文件夹下的m4a音频转换成flac for i in *m4a; do ffmpeg -i \u0026#34;$i\u0026#34; -c:a flac -compression_level 8 -map 0 -map_metadata 0 \u0026#34;${i%m4a}flac\u0026#34; \u0026amp;\u0026amp; rm \u0026#34;$i\u0026#34;; done # 把当前文件夹下所有子文件夹里的m4a音频转换成flac for f in *; do `cd \u0026#34;$f\u0026#34;; for i in *m4a; do ffmpeg -i \u0026#34;$i\u0026#34; -c:a flac -compression_level 8 -map 0 -map_metadata 0 \u0026#34;${i%m4a}flac\u0026#34; \u0026amp;\u0026amp; rm \u0026#34;$i\u0026#34;; done`; done 智能歌单创建 navidrome官方只支持编辑配置文件的智能歌单，没有图形界面的操作方式。我觉得这样太麻烦， 所以直接使用Feishin这个带有图形界面功能的桌面客户端创建。\n思考 以前总觉得互联网是开放自由的，但是国内互联网的发展却越来越封闭，各大厂商抢到用户之后马上开始封闭，就像是在圈养可以产羊毛的绵羊一样。 里面的内容搜索引擎都搜不到，逼迫用户注册、看广告、充钱。另外，国内的互联网信息丢失非常严重，以前逛的论坛、资源网站逐渐消失， 这一点从寻找失传媒体越来越火可以看出。所以，我觉得各种数据还是由自己管理保存更好。自己的东西毕竟可以做321备份策略， 丢了也怨不了谁。\n","permalink":"https://kuang-r.github.io/posts/2025-11-29-%E9%9F%B3%E4%B9%90%E7%AE%A1%E7%90%86%E7%AD%96%E7%95%A5/","summary":"\u003cp\u003e自从上班的地方不给用苹果之后，我就慢慢地将使用环境从苹果中迁移出来，\n这篇博客说的是将音乐库从 Apple Music 迁移到 navidrome 中的一些实践。\u003c/p\u003e\n\u003ch2 id=\"需求\"\u003e需求\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e智能歌单功能\u003c/li\u003e\n\u003cli\u003e可以缓存音乐的客户端\u003c/li\u003e\n\u003cli\u003e可直接扫描音乐文件夹\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e综上，选择目前能满足我需求而且开发较活跃的 navidrome 。\u003c/p\u003e\n\u003ch2 id=\"navidrome\"\u003enavidrome\u003c/h2\u003e\n\u003cp\u003e安装方面，用 docker compose 启动镜像，配置好之后可以开机启动，只要设置好 docker desktop 的开机启动即可。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 8\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 9\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e10\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e11\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e12\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e13\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e14\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e15\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e16\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eservices:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  navidrome:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    image: deluan/navidrome:latest\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    container_name: navidrome\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    user: 1000:1000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ports:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u0026#34;4533:4533\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    restart: unless-stopped # 自动重启\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    environment:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      PUID: 1000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      PGID: 1000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      TZ: Asia/Shanghai\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      ND_TRANSCODINGENABLED: true\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    volumes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u0026#34;/home/ruan/navidrome/config:/data\u0026#34; # 映射配置文件\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u0026#34;/mnt/g/Music:/music:ro\u0026#34;            # 映射音乐库\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"遇到的问题\"\u003e遇到的问题\u003c/h2\u003e\n\u003ch3 id=\"alac-无损格式无法播放\"\u003ealac 无损格式无法播放\u003c/h3\u003e\n\u003cp\u003e之前通过 apple music 无损格式管理音乐库，所以音乐格式是通过m4a容器存储的。\n但是 navidrome 的 web 页面和一部分客户端没办法直接播放m4a播放，这一点让我比较烦恼。\u003c/p\u003e","title":"音乐管理策略"},{"content":"一般来说，只要指定输入文件和输出文件的名称，ffmpeg就会自动根据后缀判定正确的格式。\nffmpeg我经常用来转换图像，存放在iCloud的图片如果小于1MB，就会自动下载。我利用这个特性，将漫画压缩到小于1MB放在iCloud上，用iPad看很方便。\n图片视频裁剪 这种用法也适用于视频。\n1 2 3 4 # crop=a:b:c:d # ab分别代表输出图片宽度和长度，cd代表裁剪矩形左上角在图片中的位置 # in_w代表输入图片的宽度，in_h代表输入文件的高度 ffmpeg -i \u0026#34;test.png\u0026#34; -vf \u0026#34;crop=in_w/2:in_h:in_w/2:0\u0026#34; output.png gif转mp4 这个需求是想要将gif转换成一段指定长度(10s)的循环播放视频。\n1 ffmpeg -i \u0026#34;test.gif\u0026#34; -ignore_loop 0 -t 10s out.mp4 视频切片 裁剪从30s开始算起的30s视频\n1 ffmpeg -i \u0026#34;test.mp4\u0026#34; -ss 00:00:30 -t 00:00:30 out.mp4 改变视频速率 将视频的速率修改为32Hz\n1 ffmpeg -i \u0026#34;test.mp4\u0026#34; -r 32 out.mp4 拼接图片 1 ffmpeg -i cat.jpg -i dog.jpg -c copy -filter_complex vstack vout.jpg ","permalink":"https://kuang-r.github.io/posts/2023-05-22-ffmpeg%E7%94%A8%E6%B3%95%E8%AE%B0%E5%BD%95/","summary":"\u003cp\u003e一般来说，只要指定输入文件和输出文件的名称，ffmpeg就会自动根据后缀判定正确的格式。\u003c/p\u003e\n\u003cp\u003effmpeg我经常用来转换图像，存放在iCloud的图片如果小于1MB，就会自动下载。我利用这个特性，将漫画压缩到小于1MB放在iCloud上，用iPad看很方便。\u003c/p\u003e\n\u003ch2 id=\"图片视频裁剪\"\u003e图片视频裁剪\u003c/h2\u003e\n\u003cp\u003e这种用法也适用于视频。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# crop=a:b:c:d\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ab分别代表输出图片宽度和长度，cd代表裁剪矩形左上角在图片中的位置\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# in_w代表输入图片的宽度，in_h代表输入文件的高度\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003effmpeg -i \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test.png\u0026#34;\u003c/span\u003e -vf \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;crop=in_w/2:in_h:in_w/2:0\u0026#34;\u003c/span\u003e output.png\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"gif转mp4\"\u003egif转mp4\u003c/h2\u003e\n\u003cp\u003e这个需求是想要将gif转换成一段指定长度(10s)的循环播放视频。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003effmpeg -i \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test.gif\u0026#34;\u003c/span\u003e -ignore_loop \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e -t 10s out.mp4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"视频切片\"\u003e视频切片\u003c/h2\u003e\n\u003cp\u003e裁剪从30s开始算起的30s视频\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003effmpeg -i \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test.mp4\u0026#34;\u003c/span\u003e -ss 00:00:30 -t 00:00:30 out.mp4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"改变视频速率\"\u003e改变视频速率\u003c/h2\u003e\n\u003cp\u003e将视频的速率修改为32Hz\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003effmpeg -i \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test.mp4\u0026#34;\u003c/span\u003e -r \u003cspan style=\"color:#ae81ff\"\u003e32\u003c/span\u003e out.mp4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"拼接图片\"\u003e拼接图片\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003effmpeg -i cat.jpg -i dog.jpg -c copy -filter_complex vstack vout.jpg\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"ffmpeg用法记录"},{"content":"一个炫酷的命令行程序它到底需要什么？\n构建系统 命令行参数解析 日志系统 代码文档系统 第三方库可以用cmake管理，自从qt官方构建系统转到cmake之后，感觉cmake基本上已经成为c++项目的事实构建系统了。 命令行参数解析和日志系统可以使用gflags和glog，代码文档系统自然是通用的doxygen。\ncmake 基本上可以把makefile淘汰掉了，makefile最致命的一点就是无法自动构建依赖。在c和c++中，源文件的头文件依赖如果使用makefile构建，要么就手动管理依赖（要命），要么就写个又长又臭的makefile来自动构建（还是要命）。在简单地学会cmake之后，就放心大胆地跟makefile说拜拜吧。\n构建工程 有一些必须添加的首行比如指定cmake版本，添加源文件。\n1 2 3 cmake_minimum_required(VERSION 3.20) project(cmdline) add_executable(${PROJECT_NAME} main.c) 还有就是引入依赖，这个工程我是基于glib做的。glib提供命令行解析、日志系统、单元测试等功能。\n1 2 3 4 find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB glib-2.0 REQUIRED) add_definitions(-DG_LOG_USE_STRUCTURED) include_directories(${GLIB_INCLUDE_DIRS}) 文档生成，引入Doxygen生成文档。\n1 2 3 4 5 find_package(Doxygen) if (DOXYGEN_FOUND) message(\u0026#34;Doxygen build start\u0026#34;) doxygen_add_docs(docs ${PROJECT_SOURCE_DIR} ALL) endif() 命令行参数解析 命令行参数解析最常用的是posix标准getopt或者gnu的getopt，qt和glib都有自己的命令行解析工具。 我使用的是glib提供的命令行解析，简单用法跟getopt差不多。不过glib这个东西还扩展了一下用法， 有group这个概念，因为文档不详细我也没仔细研究。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static GOptionEntry entries[] = { {\u0026#34;ppid\u0026#34;, \u0026#39;p\u0026#39;, 0, G_OPTION_ARG_STRING, \u0026amp;ppid, \u0026#34;Product id in apple mfi website\u0026#34;, DEFAULT_PPID}, {\u0026#34;logfile\u0026#34;, \u0026#39;l\u0026#39;, 0, G_OPTION_ARG_STRING, \u0026amp;logfile, \u0026#34;The path to log file\u0026#34;, DEFAULT_LOG_FILE}, {NULL} }; gboolean ret = FALSE; GOptionContext *context = g_option_context_new(\u0026#34;device-uuid\u0026#34;); /* setting parser */ g_option_context_add_main_entries(context, entries, NULL); g_option_context_set_summary(context, \u0026#34;This program use to enable and disable apple token\u0026#34;); /* parse it */ ret = g_option_context_parse(context, \u0026amp;argc, \u0026amp;argv, NULL); if (!ret) g_error(\u0026#34;parse err\u0026#34;); 解析完成之后，之前定义的变量就已经被改变，可以直接使用。\n日志系统 glib的文档的确是有些少，如果需要找用法的话，把代码仓库克隆下来直接学习单元测试的代码比较好。 默认设置是不会输出g_info和g_debug和g_critical的，必须定义环境变量G_MESSAGE_DEBUG=all才行。 所以如果没有改变日志系统的全局回调函数，建议还是使用g_message, g_warning和g_error作为代替。\n在这个工程中，日志我统一追加到日志文件的后面。debug由宏NDEBUG控制而且只输出到控制台， error不但输出到控制台还会输出到日志文件中。具体实现可以看main.c，下面贴出设置回调的代码。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 static GLogWriterOutput log_write( GLogLevelFlags log_level, const GLogField *fields, gsize n_fields, gpointer user_data) { ... } static void set_log_path(const char *log_path) { FILE *logfile = fopen(log_path, \u0026#34;a\u0026#34;); if (logfile == NULL) g_error(\u0026#34;open log file err: %s\\n\u0026#34;, strerror(errno)); g_log_set_writer_func(log_write, (void *)logfile, NULL); } FILE *logfile = fopen(log_path, \u0026#34;a\u0026#34;); if (logfile == NULL) g_error(\u0026#34;open log file err: %s\\n\u0026#34;, strerror(errno)); g_log_set_writer_func(log_write, (void *)logfile, NULL); 代码文档系统 直接从代码里生成文档是一件非常爽的事情，doxygen进行注释需要注意三个方面。\n配置文件 文件头标识 函数注释和变量注释 配置文件 直接命令doxygen -g生成默认配置文件DoxyFile，具体的设置可以参考官网。 在这个配置中我只改了一个变量，EXTRACT_STATIC=YES对static成员也生成注释。 一般的功能都可以用标识来实现。生成的话在上面的cmake配置文件里有写，当然直接生成也可以。\n我在工程中是直接在从CMakeLists.txt中配置Doxygen的，所以并不需要Doxygen文件。\n文件头标识 在这个文件（README.md)头加上/** \\mainpage这一行就能把这个文件作为生成文档的主页面， proxygen直接支持markdown语法，写起来还是挺爽的。\n源代码文件头要加上一些标识符，指定对这个源文件进行文档生成。\\file是必须有的， 具体可以参考官网\n1 2 3 4 5 /** * \\file main.c * \\author Ray Ruan(a1173522112@163.com) * \\date 2021-10-13 */ 注释 注释主要分两种，变量注释和一般注释。下面我展示我的用法，具体还是要看官网\n1 2 3 4 5 6 7 8 int a; /**\u0026lt; variable a */ /** * \\brief write buffer to somewhere * \\details details of this function * \\param buf buffer * \\return none */ void write(char buf[]); 工程代码 工程代码我丢到了github上，有兴趣的话可以参考一下。\n","permalink":"https://kuang-r.github.io/posts/2021-10-13-%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%82%AB%E9%85%B7%E7%9A%84%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%A8%8B%E5%BA%8F%E5%B7%A5%E7%A8%8B/","summary":"\u003cp\u003e一个炫酷的命令行程序它到底需要什么？\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e构建系统\u003c/li\u003e\n\u003cli\u003e命令行参数解析\u003c/li\u003e\n\u003cli\u003e日志系统\u003c/li\u003e\n\u003cli\u003e代码文档系统\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e第三方库可以用cmake管理，自从qt官方构建系统转到cmake之后，感觉cmake基本上已经成为c++项目的事实构建系统了。\n命令行参数解析和日志系统可以使用gflags和glog，代码文档系统自然是通用的doxygen。\u003c/p\u003e\n\u003ch2 id=\"cmake\"\u003ecmake\u003c/h2\u003e\n\u003cp\u003e基本上可以把makefile淘汰掉了，makefile最致命的一点就是无法自动构建依赖。在c和c++中，源文件的头文件依赖如果使用makefile构建，要么就手动管理依赖（要命），要么就写个又长又臭的makefile来自动构建（还是要命）。在简单地学会cmake之后，就放心大胆地跟makefile说拜拜吧。\u003c/p\u003e\n\u003ch3 id=\"构建工程\"\u003e构建工程\u003c/h3\u003e\n\u003cp\u003e有一些必须添加的首行比如指定cmake版本，添加源文件。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake_minimum_required(VERSION 3.20)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eproject(cmdline)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadd_executable(${PROJECT_NAME} main.c)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e还有就是引入依赖，这个工程我是基于glib做的。glib提供命令行解析、日志系统、单元测试等功能。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efind_package(PkgConfig REQUIRED)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epkg_check_modules(GLIB glib-2.0 REQUIRED)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadd_definitions(-DG_LOG_USE_STRUCTURED)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einclude_directories(${GLIB_INCLUDE_DIRS})\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e文档生成，引入Doxygen生成文档。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efind_package(Doxygen)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eif (DOXYGEN_FOUND)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        message(\u0026#34;Doxygen build start\u0026#34;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        doxygen_add_docs(docs ${PROJECT_SOURCE_DIR} ALL)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eendif()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"命令行参数解析\"\u003e命令行参数解析\u003c/h2\u003e\n\u003cp\u003e命令行参数解析最常用的是posix标准getopt或者gnu的getopt，qt和glib都有自己的命令行解析工具。\n我使用的是glib提供的命令行解析，简单用法跟getopt差不多。不过glib这个东西还扩展了一下用法，\n有group这个概念，因为文档不详细我也没仔细研究。\u003c/p\u003e","title":"构建一个炫酷的命令行程序工程"},{"content":"这边论文的basic idea比较简单，就是放出诱饵和不断改变网络位置（IP地址）来缓解网络侦察(reconnaissance)攻击。我认为它的实验很有意思，本来我以为会在路由器层面进行实现，通过改变IP包的方式对上层透明化。结果后来一看，发现竟然是在一台电脑上搭建虚拟机来模拟全部环境。这就是乞丐版实现吗？不过仔细一想，其实这种实验的可行性高而且也可信，简直就是最好方案啊。\n还有就是这篇论文在实现它的协议时用到了很多的知识，对这些知识进行简单的了解会对网络空间安全方向有一个大致的了解。我认为这个还是很值的注意的。\nProblem 网络攻击者会对IP地址进行探测，为了找出现有系统的缺点或者是监控这个系统。\nBasic Idea 动态改变IP地址＋大量释放诱饵(decoy)缓解网络探测攻击。而且在改变IP地址的时候还不能中断现有服务。\n收获 [ZMap]（https://www.usenix.org/system/files/conference/usenixsecurity13/sec13-paper_durumeric.pdf）能花45分钟把整个IPv4的地址探测完。 NMap是一个网络探测工具 honypots原来是用于吸引攻击者和学习攻击者模式的，在这篇论文中用来延长其扫描时间 用常用服务：ssh, ftps, sftp, udpchar, tftp来做实验 Thinking 这个方法需要大量的IP地址来释放诱饵，如果把迁移往协议栈挪上一层，到TCP/UDP层面会不会降低开销呢？但是端口号只有65535个，如果只在这么多个端口号中进行randomization会不会显得有些不够用？考虑到吞吐量，应该只是需要迁移端口就足够了。\n","permalink":"https://kuang-r.github.io/posts/2021-10-07-desir-decoy-enhanced-seamless-ip-randomization%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0/","summary":"\u003cp\u003e这边论文的basic idea比较简单，就是放出诱饵和不断改变网络位置（IP地址）来缓解网络侦察(reconnaissance)攻击。我认为它的实验很有意思，本来我以为会在路由器层面进行实现，通过改变IP包的方式对上层透明化。结果后来一看，发现竟然是在一台电脑上搭建虚拟机来模拟全部环境。这就是乞丐版实现吗？不过仔细一想，其实这种实验的可行性高而且也可信，简直就是最好方案啊。\u003c/p\u003e\n\u003cp\u003e还有就是这篇论文在实现它的协议时用到了很多的知识，对这些知识进行简单的了解会对网络空间安全方向有一个大致的了解。我认为这个还是很值的注意的。\u003c/p\u003e\n\u003ch3 id=\"problem\"\u003eProblem\u003c/h3\u003e\n\u003cp\u003e网络攻击者会对IP地址进行探测，为了找出现有系统的缺点或者是监控这个系统。\u003c/p\u003e\n\u003ch3 id=\"basic-idea\"\u003eBasic Idea\u003c/h3\u003e\n\u003cp\u003e动态改变IP地址＋大量释放诱饵(decoy)缓解网络探测攻击。而且在改变IP地址的时候还不能中断现有服务。\u003c/p\u003e\n\u003ch3 id=\"收获\"\u003e收获\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e[ZMap]（https://www.usenix.org/system/files/conference/usenixsecurity13/sec13-paper_durumeric.pdf）能花45分钟把整个IPv4的地址探测完。\u003c/li\u003e\n\u003cli\u003eNMap是一个网络探测工具\u003c/li\u003e\n\u003cli\u003ehonypots原来是用于吸引攻击者和学习攻击者模式的，在这篇论文中用来延长其扫描时间\u003c/li\u003e\n\u003cli\u003e用常用服务：ssh, ftps, sftp, udpchar, tftp来做实验\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"thinking\"\u003eThinking\u003c/h3\u003e\n\u003cp\u003e这个方法需要大量的IP地址来释放诱饵，如果把迁移往协议栈挪上一层，到TCP/UDP层面会不会降低开销呢？但是端口号只有65535个，如果只在这么多个端口号中进行randomization会不会显得有些不够用？考虑到吞吐量，应该只是需要迁移端口就足够了。\u003c/p\u003e","title":"Decoy-Enhanced Seamless IP Randomization阅读笔记"},{"content":"最近对Web技术提起了一些兴趣，想学学web开发。现在搭建网站据我所知，PHP和java用的最多。但我就是喜欢特立独行，想试试别的东西。发现asp.net貌似不错，我对c#的观感挺好，而且现在.net框架也开源并支持跨平台了。所以就在vs上安装了.net的开发环境，准备学一学。\n初始化一个工程后，看到运行环境里有docker。这东西这几年貌似很火，之前在图书馆里有看过相关的书籍，里面写的高深莫测，什么容器，什么集群花里胡哨也没详细看。正好趁现在有兴趣也学一学docker。\n官方教程 上官网看了下，发现现在docker在windows下推出了desktop这个图形界面用来管理运行中的状态，而且整个界面还设计得很不错，简单易用。下载了安装包，配个版本较新的windows就能直接用。核心是用微软的wsl2跑的，原来微软切换到wsl2还有这个好处，毕竟有些东西只有Linux内核才跑的动啊。\n打开docker desktop之后，会弹出一个框教新手怎么用的。我点了进去，发现这个教程直接就是一个用docker运行的一个http服务。首先是直接用git image把教程仓库clone下来，然后直接将这个仓库编译成docker的image，再运行这个image，就能直接在浏览器上访问localhost阅读这个教程啦。\n这一下子吸引住了我：寥寥几步，就把docker的作用和使用步骤跟教程紧密结合在了一起，实在是很有意思。所以说，这种新兴的计算机技术或者是语言，看多少书都不如上官网看一遍tutorial然后实操，效果差太多了。一个优秀的项目肯定有优秀的官方教程，如果没有，说明它还不够优秀。\n核心概念 感觉docker就是个虚拟机，专门设计用于运行服务的。下面以我的理解（仅仅是操作完了官方教程的水平）描述一下一些相关概念。\nimage 一个包含了程序和所需依赖的包，用docker构建\ncontainer 每次run image都会产出一个新的container，用来保存每次运行产生的变化，比如说环境变量，配置文件什么的。\nvolumes 有一些文件要保存在container之外的地方，这样更新image再运行container的时候，中间数据就不会丢失了。这个地方就叫volumes。\nnetwork container之间用network通信，处于同一个network的运行实例能相互通讯。\n应用 总的来说，感觉这东西适合运行一些不会关闭的软件，比如监听80端口的web服务。也有一些很有意思的应用，比较广泛的应该就是github actions。jekyll就能通过docker来构建和发布GitHub pages。参考helaili写的jekyll-action\n在了解过docker的操作流程和基本概念之后，这东西很容易搞懂。原理就是创建一个ruby的container，在这个环境里运行一个简单的shell脚本。这个脚本的作用是下载仓库-\u0026gt;安装jekyll依赖-\u0026gt;构建jekyll-\u0026gt;发布网站。非常有意思，脚本名字是entrypoint.sh，有兴趣的可以看看。\n我跟着这个仓库的README试了一下，真的非常实用。再也不用局限于GitHub自动构建的jekyll版本和插件啦，超爽！\n像这种CI(Continuous integration)工具，能实现很高的自动化。像是打包发布安装包，运行单元测试之类的机械性工作都能完全自动运行。花在构建和学习自动化工具的时间我认为是非常值得的。CI工具走的比较前的貌似是gitlab，glib库就是很标准的例子，还有就是gtk的官网也是用CI构建的。github算是比较晚的，2018年才推出。\n参考 Docker Desktop\nIntroduction to GitHub Actions\n","permalink":"https://kuang-r.github.io/posts/2021-08-19-docker%E5%88%9D%E6%8E%A2/","summary":"\u003cp\u003e最近对Web技术提起了一些兴趣，想学学web开发。现在搭建网站据我所知，PHP和java用的最多。但我就是喜欢特立独行，想试试别的东西。发现asp.net貌似不错，我对c#的观感挺好，而且现在.net框架也开源并支持跨平台了。所以就在vs上安装了.net的开发环境，准备学一学。\u003c/p\u003e\n\u003cp\u003e初始化一个工程后，看到运行环境里有docker。这东西这几年貌似很火，之前在图书馆里有看过相关的书籍，里面写的高深莫测，什么容器，什么集群花里胡哨也没详细看。正好趁现在有兴趣也学一学docker。\u003c/p\u003e\n\u003ch2 id=\"官方教程\"\u003e官方教程\u003c/h2\u003e\n\u003cp\u003e上官网看了下，发现现在docker在windows下推出了desktop这个图形界面用来管理运行中的状态，而且整个界面还设计得很不错，简单易用。下载了安装包，配个版本较新的windows就能直接用。核心是用微软的wsl2跑的，原来微软切换到wsl2还有这个好处，毕竟有些东西只有Linux内核才跑的动啊。\u003c/p\u003e\n\u003cp\u003e打开docker desktop之后，会弹出一个框教新手怎么用的。我点了进去，发现这个教程直接就是一个用docker运行的一个http服务。首先是直接用git image把教程仓库clone下来，然后直接将这个仓库编译成docker的image，再运行这个image，就能直接在浏览器上访问localhost阅读这个教程啦。\u003c/p\u003e\n\u003cp\u003e这一下子吸引住了我：寥寥几步，就把docker的作用和使用步骤跟教程紧密结合在了一起，实在是很有意思。所以说，这种新兴的计算机技术或者是语言，看多少书都不如上官网看一遍tutorial然后实操，效果差太多了。一个优秀的项目肯定有优秀的官方教程，如果没有，说明它还不够优秀。\u003c/p\u003e\n\u003ch2 id=\"核心概念\"\u003e核心概念\u003c/h2\u003e\n\u003cp\u003e感觉docker就是个虚拟机，专门设计用于运行服务的。下面以我的理解（仅仅是操作完了官方教程的水平）描述一下一些相关概念。\u003c/p\u003e\n\u003ch3 id=\"image\"\u003eimage\u003c/h3\u003e\n\u003cp\u003e一个包含了程序和所需依赖的包，用docker构建\u003c/p\u003e\n\u003ch3 id=\"container\"\u003econtainer\u003c/h3\u003e\n\u003cp\u003e每次run image都会产出一个新的container，用来保存每次运行产生的变化，比如说环境变量，配置文件什么的。\u003c/p\u003e\n\u003ch3 id=\"volumes\"\u003evolumes\u003c/h3\u003e\n\u003cp\u003e有一些文件要保存在container之外的地方，这样更新image再运行container的时候，中间数据就不会丢失了。这个地方就叫volumes。\u003c/p\u003e\n\u003ch3 id=\"network\"\u003enetwork\u003c/h3\u003e\n\u003cp\u003econtainer之间用network通信，处于同一个network的运行实例能相互通讯。\u003c/p\u003e\n\u003ch2 id=\"应用\"\u003e应用\u003c/h2\u003e\n\u003cp\u003e总的来说，感觉这东西适合运行一些不会关闭的软件，比如监听80端口的web服务。也有一些很有意思的应用，比较广泛的应该就是github actions。jekyll就能通过docker来构建和发布GitHub pages。参考helaili写的\u003ca href=\"https://github.com/helaili/jekyll-action\"\u003ejekyll-action\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e在了解过docker的操作流程和基本概念之后，这东西很容易搞懂。原理就是创建一个ruby的container，在这个环境里运行一个简单的shell脚本。这个脚本的作用是下载仓库-\u0026gt;安装jekyll依赖-\u0026gt;构建jekyll-\u0026gt;发布网站。非常有意思，脚本名字是\u003ccode\u003eentrypoint.sh\u003c/code\u003e，有兴趣的可以看看。\u003c/p\u003e\n\u003cp\u003e我跟着这个仓库的README试了一下，真的非常实用。再也不用局限于GitHub自动构建的jekyll版本和插件啦，\u003ca href=\"https://github.com/kuang-R/jekyll-action-test\"\u003e超爽\u003c/a\u003e！\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"自动构建效果图\" loading=\"lazy\" src=\"/imgs/210819-01.png\"\u003e\u003c/p\u003e\n\u003cp\u003e像这种CI(Continuous integration)工具，能实现很高的自动化。像是打包发布安装包，运行单元测试之类的机械性工作都能完全自动运行。花在构建和学习自动化工具的时间我认为是非常值得的。CI工具走的比较前的貌似是gitlab，\u003ca href=\"https://gitlab.gnome.org/GNOME/glib\"\u003eglib库\u003c/a\u003e就是很标准的例子，还有就是\u003ca href=\"https://gitlab.gnome.org/Infrastructure/gtk-web\"\u003egtk的官网\u003c/a\u003e也是用CI构建的。github算是比较晚的，2018年才推出。\u003c/p\u003e\n\u003ch2 id=\"参考\"\u003e参考\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://www.docker.com/products/docker-desktop\"\u003eDocker Desktop\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://docs.github.com/en/actions/learn-github-actions/introduction-to-github-actions#the-components-of-github-actions\"\u003eIntroduction to GitHub Actions\u003c/a\u003e\u003c/p\u003e","title":"Docker初探"},{"content":"我一直都对C语言情有独钟，是受《C语言点滴》这本书的影响。glib库作为一整个gnome的底层架构，在实现了类似于c++ std库的功能下，还包括了文件系统，多线程，定时器这些跨平台的方便组件。在跨语言领域上，也有完善的g-object系统bind各种语言。如果需要编写一个完善的库，可以说使用glib是非常合适的。我准备过一遍glib参考手册，然后再读一读源码，写一些使用这个库的使用方法和抽象概念。\n前几天glib官方的参考手册移到了gtk的域名下进行管理，整个界面变得现代化了很多。加上之前的gtk官网更新，感觉gtk系列也要慢慢地崛起了。当然，跟qt系的使用率还是没法比。\n基础数据结构可以类比c++的std标准库，数据结构只包括glib库的一部分。论使用的便利当然是不如c++的，但加上glib的其它各种组件，用起来还是很不错。如果想要弄清楚用法，直接查看glib代码仓库的单元测试最正确全面。在这里只简单谈谈我感兴趣的地方。\nGArray 类似于c++中的vector，但是功能没有那么强大。new的时候需要指定数组元素的大小，但是不需要指定元素个数。也就是说new出来的GArray都是空数组。而且也不能一个一个地添加元素，只能添加数组。内置有排序，二分查找，引用计数，各种删除操作。\n将这个数据结构跟vector进行对比其实是不合适的，vector致力于取代c的数组，而GArray则是对c数组进行补充。从只能append_vals中就可以看出来，用法大约是先暂存在c数组里，然后一次性添加到GArray中，再进行各种操作。当然，一个一个地添加也是可以的。\n1 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 #include \u0026lt;glib.h\u0026gt; gint comp(gconstpointer a, gconstpointer b) { double x = *(double *)a; double y = *(double *)b; if (x \u0026lt; y) return -1; else if (x \u0026gt; y) return 1; else return 0; } int main() { GArray *arr = g_array_new(FALSE, FALSE, sizeof(double)); double t[] = {1., 5., 6., 8., 3., 9.}; g_array_append_vals(arr, t, sizeof(t)/sizeof(double)); g_array_sort(arr, comp); g_print(\u0026#34;len: %d\\n\u0026#34;, arr-\u0026gt;len); // len: 6 double *p = (double *)arr-\u0026gt;data; /* 1.000000 3.000000 5.000000 6.000000 8.000000 9.000000 */ for (int i = 0; i \u0026lt; arr-\u0026gt;len; i++) g_print(\u0026#34;%lf \u0026#34;, p[i]); } GByteArray 字节数组，是GArray的子集，元素类型固定为Byte，在使用上方便很多。\nGPtrArray 保存指针的数组，根据new的方法决定free的时候是否把指针指向的内容也给free掉。\nGString 我没在参考手册中的GString对应方法中找到new，所以用了g_malloc创建GString，结果g_print没办法输出了。看来这些数据结构如果没用专门的new创建的话，会产生不可知的效果。\n惯例的增删查改操作，值得注意的是明确指定使用utf-8编码，也就是说c源文件必须是utf-8的编码吧。\nGStringChunk 貌似是用来管理一大堆字符串？insert之后会复制对应内存到这个数据结构里面，然后返回对应的字符串指针。因为是统一分配销毁，所以内存开销会比用GString小很多，但我想象不出来需要用到它的场景。\nGHashTable 以Hash表的形式实现的map或者是set，创建的时候需要指定Hash函数和判等函数。因为内部存储的是指针，所以在销毁对象时需要free。当然，也可以在new时指定销毁函数。insert时如果key在表中已存在，只更新value，replace则会更新key和value。\n1 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 29 30 31 32 33 34 35 36 37 38 #include \u0026lt;glib.h\u0026gt; #include \u0026lt;string.h\u0026gt; guint gs_hash(gconstpointer key) { const GString *k = key; return g_str_hash(k-\u0026gt;str); } gboolean eq(gconstpointer a, gconstpointer b) { return strcmp(a, b) == 0; } void gs_free(gpointer data) { g_print(\u0026#34;destory key\\n\u0026#34;); g_string_free((GString *)data, TRUE); } void print_dict(gpointer key, gpointer value, gpointer user_data) { const GString *s = key; g_print(\u0026#34;\\\u0026#34;%s\\\u0026#34;: %d\\n\u0026#34;, s-\u0026gt;str, *(int *)value); } int main() { /* like set\u0026lt;string, int\u0026gt; */ GHashTable *dict = g_hash_table_new_full(gs_hash, eq, gs_free, g_free); for (int i = 0; i \u0026lt; 1000; i++) { GString *st = g_string_new(\u0026#34;\u0026#34;); int *it = g_malloc(sizeof(int)); g_string_printf(st, \u0026#34;%d\u0026#34;, i); *it = i; g_hash_table_insert(dict, st, it); } g_hash_table_foreach(dict, print_dict, NULL); g_hash_table_destroy(dict); } 这东西写起来有够累人……还有就是，insert会覆盖相同值的key，在这里被覆盖掉的值如果在创建时没有指定DestroyNotify函数，会产生内存泄漏。\nBytes 不可变的字节序列，主要以引用计数的方式使用。按照官方文档所说，用GBytes作为key可以跟GHashTable和GTree很好地结合使用。有意思的是它有几种不同的new方法。\n看到这里，我认为glib肯定有一种方法能方便地简化这些累人的写法，可能是引用计数或者是其它的什么。看来有需要对glib的内存管理和类型系统来一个概括性的探索。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include \u0026lt;glib.h\u0026gt; static int s_i = 100; int main() { GBytes *gb = g_bytes_new(\u0026amp;s_i, sizeof(int)); GBytes *st = g_bytes_new_static(\u0026amp;s_i, sizeof(int)); g_print(\u0026#34;new: %d\\n\u0026#34;, *(int *)g_bytes_get_data(gb, NULL)); // new: 100 g_print(\u0026#34;new_static: %d\\n\u0026#34;, *(int *)g_bytes_get_data(st, NULL)); // new_static: 100 s_i = 200; g_print(\u0026#34;new: %d\\n\u0026#34;, *(int *)g_bytes_get_data(gb, NULL)); // new: 100 g_print(\u0026#34;new_static: %d\\n\u0026#34;, *(int *)g_bytes_get_data(st, NULL)); // new_static: 200 g_bytes_unref(gb); gb = NULL; g_bytes_unref(st); st = NULL; } GList 双向链表。找了一番，竟然没有找到new方法，结果到源码单元测试里看才知道根本不用初始化。没有元素就是直接NULL，也就是说这种链表并没有头结点这种东西。\n1 2 3 4 5 6 7 8 #include \u0026lt;glib.h\u0026gt; int main(int argc, char **argv) { GList *list = NULL; g_print(\u0026#34;len: %d\\n\u0026#34;, g_list_length(list)); // len: 0 list = g_list_append(list, \u0026#34;test\u0026#34;); g_print(\u0026#34;len: %d\\n\u0026#34;, g_list_length(list)); // len: 1 g_list_free(list); } GSList 单向链表，用法同上\nGQueue 先进先出队列，没什么特别的。\nGTree 按照文档描述，是平衡二叉树结构，跟红黑树相比查找效率更高。\n参考 Manage C data using the GLib collections，2005年的一篇glib指导，详尽且全面，真正的大佬。\nGLib – 2.0 - GTK Documentation\n","permalink":"https://kuang-r.github.io/posts/2021-08-13-glib%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01---%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/","summary":"\u003cp\u003e我一直都对C语言情有独钟，是受《C语言点滴》这本书的影响。glib库作为一整个gnome的底层架构，在实现了类似于c++ std库的功能下，还包括了文件系统，多线程，定时器这些跨平台的方便组件。在跨语言领域上，也有完善的g-object系统bind各种语言。如果需要编写一个完善的库，可以说使用glib是非常合适的。我准备过一遍glib参考手册，然后再读一读源码，写一些使用这个库的使用方法和抽象概念。\u003c/p\u003e\n\u003cp\u003e前几天glib官方的参考手册移到了gtk的域名下进行管理，整个界面变得现代化了很多。加上之前的gtk官网更新，感觉gtk系列也要慢慢地崛起了。当然，跟qt系的使用率还是没法比。\u003c/p\u003e\n\u003cp\u003e基础数据结构可以类比c++的std标准库，数据结构只包括glib库的一部分。论使用的便利当然是不如c++的，但加上glib的其它各种组件，用起来还是很不错。如果想要弄清楚用法，直接查看glib代码仓库的单元测试最正确全面。在这里只简单谈谈我感兴趣的地方。\u003c/p\u003e\n\u003ch3 id=\"garray\"\u003eGArray\u003c/h3\u003e\n\u003cp\u003e类似于c++中的vector，但是功能没有那么强大。new的时候需要指定数组元素的大小，但是不需要指定元素个数。也就是说new出来的GArray都是空数组。而且也不能一个一个地添加元素，只能添加数组。内置有排序，二分查找，引用计数，各种删除操作。\u003c/p\u003e\n\u003cp\u003e将这个数据结构跟vector进行对比其实是不合适的，vector致力于取代c的数组，而GArray则是对c数组进行补充。从只能append_vals中就可以看出来，用法大约是先暂存在c数组里，然后一次性添加到GArray中，再进行各种操作。当然，一个一个地添加也是可以的。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 8\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 9\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e10\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e11\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e12\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e13\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e14\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e15\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e16\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e17\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e18\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e19\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e20\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e21\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e22\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e23\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e24\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e25\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e26\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;glib.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egint \u003cspan style=\"color:#a6e22e\"\u003ecomp\u003c/span\u003e(gconstpointer a, gconstpointer b)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)a;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)b;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e y)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e y)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tGArray \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003earr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eg_array_new\u003c/span\u003e(FALSE, FALSE, \u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e t[] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\u003cspan style=\"color:#ae81ff\"\u003e1.\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e5.\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e6.\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e8.\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3.\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e9.\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eg_array_append_vals\u003c/span\u003e(arr, t, \u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(t)\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eg_array_sort\u003c/span\u003e(arr, comp);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eg_print\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;len: %d\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, arr\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003elen); \u003cspan style=\"color:#75715e\"\u003e// len: 6\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ep \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)arr\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003edata;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e/* 1.000000 3.000000 5.000000 6.000000 8.000000 9.000000 */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e arr\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003elen; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eg_print\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%lf \u0026#34;\u003c/span\u003e, p[i]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch3 id=\"gbytearray\"\u003eGByteArray\u003c/h3\u003e\n\u003cp\u003e字节数组，是GArray的子集，元素类型固定为Byte，在使用上方便很多。\u003c/p\u003e","title":"glib学习笔记1 - 基础数据结构"},{"content":"有时用vim打开一些文件时，会显示乱码。打开一些专辑的cue文件时，foorbar2000也会显示乱码。这都是编码不一样在作怪。 我受编码问题的苦久矣，从日常用msys2环境下的一些不兼容，到串口调试乱码问题，甚至在编程时使用注释和git时，都有乱码的困扰。\n编码不统一的弊病是历史遗留问题，最开始使用计算机的家伙们只用英文。而英文总共就26个字符加上一些其他符号，所以所有的可打印字符只需要用8位的char就可以全部保存。后来等到使用其它语言的人们也需要打印字符时，8位的char就没办法保存了。在这期间，出现了各种解决方案，这就是编码问题的起源。\n关于编码的问题，Li Yucang的 彻底弄懂Unicode编码 已经讲的非常透彻，我就不再详细复述。\n我之前听说utf-8时在Plan 9中发明，然后被各种Unix变体接受，从而广泛使用的。涛叔的 UTF-8往事 有提到这方面的一些历史。\nuchardet 这是一个从Mozilla项目中整出来的检测编码工具，ByVoid的 博客 有讲到这个工具诞生的一些事\niconv 通用的编码转换工具\n实践 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 $ ls CDImage.cue $ uchardet.exe CDImage.cue SHIFT_JIS $ iconv.exe -f shift-jis -t utf-8 CDImage.cue \u0026gt;CDImage-utf8.cue $ iconv.exe -f shift-jis -t gbk CDImage.cue \u0026gt;CDImage-gbk.cue $ ls CDImage.cue CDImage-gbk.cue CDImage-utf8.cue $ head CDImage.cue PERFORMER \u0026#34;\u0026#34; TITLE \u0026#34;▒N▒h▒▒ӂ▒▒[ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒T▒FKud Wafter Original SoundTrack\u0026#34; FILE \u0026#34;CDImage.wav\u0026#34; WAVE TRACK 01 AUDIO TITLE \u0026#34;Track01\u0026#34; PERFORMER \u0026#34;\u0026#34; INDEX 01 00:00:00 TRACK 02 AUDIO TITLE \u0026#34;Track02\u0026#34; PERFORMER \u0026#34;\u0026#34; $ head CDImage-gbk.cue PERFORMER \u0026#34;\u0026#34; TITLE \u0026#34;▒▒▒ɤ▒դ▒▒` ▒▒▒▒▒޶▒▒▒ ▒▒▒▒▒ص䣺Kud Wafter Original SoundTrack\u0026#34; FILE \u0026#34;CDImage.wav\u0026#34; WAVE TRACK 01 AUDIO TITLE \u0026#34;Track01\u0026#34; PERFORMER \u0026#34;\u0026#34; INDEX 01 00:00:00 TRACK 02 AUDIO TITLE \u0026#34;Track02\u0026#34; PERFORMER \u0026#34;\u0026#34; $ head CDImage-utf8.cue PERFORMER \u0026#34;\u0026#34; TITLE \u0026#34;クドわふたー 初回限定版 初回特典：Kud Wafter Original SoundTrack\u0026#34; FILE \u0026#34;CDImage.wav\u0026#34; WAVE TRACK 01 AUDIO TITLE \u0026#34;Track01\u0026#34; PERFORMER \u0026#34;\u0026#34; INDEX 01 00:00:00 TRACK 02 AUDIO TITLE \u0026#34;Track02\u0026#34; PERFORMER \u0026#34;\u0026#34; ","permalink":"https://kuang-r.github.io/posts/2021-08-09-%E8%B0%88%E4%B8%80%E4%B8%8B%E7%BC%96%E7%A0%81%E9%97%AE%E9%A2%98/","summary":"\u003cp\u003e有时用vim打开一些文件时，会显示乱码。打开一些专辑的cue文件时，foorbar2000也会显示乱码。这都是编码不一样在作怪。 我受编码问题的苦久矣，从日常用msys2环境下的一些不兼容，到串口调试乱码问题，甚至在编程时使用注释和git时，都有乱码的困扰。\u003c/p\u003e\n\u003cp\u003e编码不统一的弊病是历史遗留问题，最开始使用计算机的家伙们只用英文。而英文总共就26个字符加上一些其他符号，所以所有的可打印字符只需要用8位的char就可以全部保存。后来等到使用其它语言的人们也需要打印字符时，8位的char就没办法保存了。在这期间，出现了各种解决方案，这就是编码问题的起源。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e关于编码的问题，Li Yucang的 \u003ca href=\"https://liyucang-git.github.io/2019/06/17/%E5%BD%BB%E5%BA%95%E5%BC%84%E6%87%82Unicode%E7%BC%96%E7%A0%81/\"\u003e彻底弄懂Unicode编码\u003c/a\u003e 已经讲的非常透彻，我就不再详细复述。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e我之前听说utf-8时在Plan 9中发明，然后被各种Unix变体接受，从而广泛使用的。涛叔的 \u003ca href=\"https://taoshu.in/utf-8.html\"\u003eUTF-8往事\u003c/a\u003e 有提到这方面的一些历史。\u003c/p\u003e\n\u003ch3 id=\"uchardet\"\u003euchardet\u003c/h3\u003e\n\u003cp\u003e这是一个从Mozilla项目中整出来的检测编码工具，ByVoid的 \u003ca href=\"https://byvoid.com/zhs/blog/encoding-autodetector-uchardet/\"\u003e博客\u003c/a\u003e 有讲到这个工具诞生的一些事\u003c/p\u003e\n\u003ch3 id=\"iconv\"\u003eiconv\u003c/h3\u003e\n\u003cp\u003e通用的编码转换工具\u003c/p\u003e\n\u003ch3 id=\"实践\"\u003e实践\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 8\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 9\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e10\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e11\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e12\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e13\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e14\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e15\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e16\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e17\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e18\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e19\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e20\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e21\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e22\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e23\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e24\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e25\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e26\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e27\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e28\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e29\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e30\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e31\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e32\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e33\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e34\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e35\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e36\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e37\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e38\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e39\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e40\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e41\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e42\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e43\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e44\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e45\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e46\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e47\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e48\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ ls\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCDImage.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ uchardet.exe CDImage.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSHIFT_JIS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ iconv.exe -f shift-jis -t utf-8 CDImage.cue \u0026gt;CDImage-utf8.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ iconv.exe -f shift-jis -t gbk CDImage.cue \u0026gt;CDImage-gbk.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ ls\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCDImage.cue  CDImage-gbk.cue  CDImage-utf8.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ head CDImage.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;▒N▒h▒▒ӂ▒▒[ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒T▒FKud Wafter Original SoundTrack\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFILE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CDImage.wav\u0026#34;\u003c/span\u003e WAVE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  TRACK \u003cspan style=\"color:#ae81ff\"\u003e01\u003c/span\u003e AUDIO\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  TITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Track01\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  PERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INDEX \u003cspan style=\"color:#ae81ff\"\u003e01\u003c/span\u003e 00:00:00\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTRACK \u003cspan style=\"color:#ae81ff\"\u003e02\u003c/span\u003e AUDIO\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Track02\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ head CDImage-gbk.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;▒▒▒ɤ▒դ▒▒` ▒▒▒▒▒޶▒▒▒ ▒▒▒▒▒ص䣺Kud Wafter Original SoundTrack\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFILE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CDImage.wav\u0026#34;\u003c/span\u003e WAVE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  TRACK \u003cspan style=\"color:#ae81ff\"\u003e01\u003c/span\u003e AUDIO\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  TITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Track01\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  PERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INDEX \u003cspan style=\"color:#ae81ff\"\u003e01\u003c/span\u003e 00:00:00\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTRACK \u003cspan style=\"color:#ae81ff\"\u003e02\u003c/span\u003e AUDIO\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Track02\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ head CDImage-utf8.cue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;クドわふたー 初回限定版 初回特典：Kud Wafter Original SoundTrack\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFILE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CDImage.wav\u0026#34;\u003c/span\u003e WAVE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  TRACK \u003cspan style=\"color:#ae81ff\"\u003e01\u003c/span\u003e AUDIO\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  TITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Track01\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  PERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INDEX \u003cspan style=\"color:#ae81ff\"\u003e01\u003c/span\u003e 00:00:00\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTRACK \u003cspan style=\"color:#ae81ff\"\u003e02\u003c/span\u003e AUDIO\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTITLE \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Track02\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePERFORMER \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"谈一下编码问题"},{"content":"我用apple music听音乐。天天静听是我用的第一个音乐软件，之后是qq音乐，再之后是网易云音乐。用过的这些软件都有些不合心意，没有那种能用一辈子的感觉。就拿网易云音乐来说吧，因为版权问题各种没法听，明明昨天可以听，今天就不行；曲库不全；喜欢的音乐莫名其妙的消失；烦人的各种社交功能；官方发过来的不定期废话软文……\napple music最好用的是上传功能，我能上传自己的音乐。上传的音乐统一存在音乐库进行管理。上传之后我能用电脑，手机各个平台听。还有就是它是一款纯粹的音乐软件，没有广告，没有社交，用起来像在用MP3。再有就是价格便宜，国区每个月也就10块钱，配有近乎无限的音乐上传数目，现有的音乐全部能听。除了曲库不太全外，基本上没有任何的缺点。而曲库不太全在完善的上传功能下也不算什么缺点了。\n知乎用户守护未来有一篇文章提到apple music的廉价订阅方法，我用的是合租。\n如何管理自己的音乐 依靠两个工具mp3tag, foobar2000，以专辑为单位管理音乐。简单来说就是将专辑歌曲统一转换成Apple lossless格式，找不到无损的就按照原样保存，然后用mp3tag打上合适的标签，专辑封面也保存好。用itunes传上自己的资料库，音乐文件夹同步上传到云盘进行备份。\nfoorbar2000 强大无匹的音乐播放器。基本上你能找得到的音乐格式它都能播放，有些需要安装相应的插件。我最喜欢它的音乐格式转换功能，能把标签也保存下来，无敌！\nMp3Tag 虽然名字叫mp3，但是所有的音乐格式都能打上标签（被名字耽误？）。标签有很多种，我以苹果音乐中会使用到的标签作为标准。\n名称 作用 Title 歌曲题目 Artist 一般是歌手 Album 专辑名 Year 发行年份 Track 第几首 Genre 种类 Album Artist 专辑作者 Discnumber 第几张碟 注意 如果一个专辑中有不同的artist，就需要特地填入album artist，否则苹果音乐会识别为两个不同的专辑。也就是说，它通过专辑名+作者的方式标识专辑。\n苹果音乐上传时会用某种算法自动匹配曲库，如果没有匹配成功才会上传。其实《歌物语》在曲库中是有的，但我不喜欢那版封面还有罗马音的歌名，所以才重新上传。也就是说可以随意修改自己上传的歌曲的标签。\n可以把苹果音乐中的歌当成MP3/320K的音质，因为我上传的无损音乐并没有无损标志。听工友说BSD16bit的音乐和BSD24bit的音乐听起来很不一样，而24bit和32bit的音乐就听不出什么差别。而CD的位数是16bit，再加上压缩编码……因为我听不出MP3/320K和CD格式有什么不同，所以我对这方面倒不是很纠结（主要是莫得钱）。\n安卓端也有苹果音乐软件……\n","permalink":"https://kuang-r.github.io/posts/2021-08-02-%E6%88%91%E6%80%8E%E4%B9%88%E5%90%AC%E9%9F%B3%E4%B9%90/","summary":"\u003cp\u003e我用apple music听音乐。天天静听是我用的第一个音乐软件，之后是qq音乐，再之后是网易云音乐。用过的这些软件都有些不合心意，没有那种能用一辈子的感觉。就拿网易云音乐来说吧，因为版权问题各种没法听，明明昨天可以听，今天就不行；曲库不全；喜欢的音乐莫名其妙的消失；烦人的各种社交功能；官方发过来的不定期废话软文……\u003c/p\u003e\n\u003cp\u003eapple music最好用的是上传功能，我能上传自己的音乐。上传的音乐统一存在音乐库进行管理。上传之后我能用电脑，手机各个平台听。还有就是它是一款纯粹的音乐软件，没有广告，没有社交，用起来像在用MP3。再有就是价格便宜，国区每个月也就10块钱，配有近乎无限的音乐上传数目，现有的音乐全部能听。除了曲库不太全外，基本上没有任何的缺点。而曲库不太全在完善的上传功能下也不算什么缺点了。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e知乎用户\u003ca href=\"https://www.zhihu.com/people/xiaote\"\u003e守护未来\u003c/a\u003e有一篇\u003ca href=\"https://zhuanlan.zhihu.com/p/373693374\"\u003e文章\u003c/a\u003e提到apple music的廉价订阅方法，我用的是合租。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"如何管理自己的音乐\"\u003e如何管理自己的音乐\u003c/h2\u003e\n\u003cp\u003e依靠两个工具\u003ccode\u003emp3tag\u003c/code\u003e, \u003ccode\u003efoobar2000\u003c/code\u003e，以专辑为单位管理音乐。简单来说就是将专辑歌曲统一转换成\u003ccode\u003eApple lossless\u003c/code\u003e格式，找不到无损的就按照原样保存，然后用mp3tag打上合适的标签，专辑封面也保存好。用itunes传上自己的资料库，音乐文件夹同步上传到云盘进行备份。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"音乐文件夹截图\" loading=\"lazy\" src=\"/imgs/210802-04.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"资料库截图\" loading=\"lazy\" src=\"/imgs/210802-02.jpg\"\u003e\u003c/p\u003e\n\u003ch3 id=\"foorbar2000\"\u003efoorbar2000\u003c/h3\u003e\n\u003cp\u003e强大无匹的音乐播放器。基本上你能找得到的音乐格式它都能播放，有些需要安装相应的插件。我最喜欢它的音乐格式转换功能，能把标签也保存下来，无敌！\u003c/p\u003e\n\u003ch3 id=\"mp3tag\"\u003eMp3Tag\u003c/h3\u003e\n\u003cp\u003e虽然名字叫mp3，但是所有的音乐格式都能打上标签（被名字耽误？）。标签有很多种，我以苹果音乐中会使用到的标签作为标准。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"标签截图\" loading=\"lazy\" src=\"/imgs/210802-01.png\"\u003e\n\u003cimg alt=\"专辑截图\" loading=\"lazy\" src=\"/imgs/210802-03.jpg\"\u003e\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e名称\u003c/th\u003e\n          \u003cth\u003e作用\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eTitle\u003c/td\u003e\n          \u003ctd\u003e歌曲题目\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eArtist\u003c/td\u003e\n          \u003ctd\u003e一般是歌手\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eAlbum\u003c/td\u003e\n          \u003ctd\u003e专辑名\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eYear\u003c/td\u003e\n          \u003ctd\u003e发行年份\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eTrack\u003c/td\u003e\n          \u003ctd\u003e第几首\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eGenre\u003c/td\u003e\n          \u003ctd\u003e种类\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eAlbum Artist\u003c/td\u003e\n          \u003ctd\u003e专辑作者\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eDiscnumber\u003c/td\u003e\n          \u003ctd\u003e第几张碟\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"注意\"\u003e注意\u003c/h3\u003e\n\u003cp\u003e如果一个专辑中有不同的\u003ccode\u003eartist\u003c/code\u003e，就需要特地填入\u003ccode\u003ealbum artist\u003c/code\u003e，否则苹果音乐会识别为两个不同的专辑。也就是说，它通过专辑名+作者的方式标识专辑。\u003c/p\u003e\n\u003cp\u003e苹果音乐上传时会用某种算法自动匹配曲库，如果没有匹配成功才会上传。其实《歌物语》在曲库中是有的，但我不喜欢那版封面还有罗马音的歌名，所以才重新上传。也就是说可以随意修改自己上传的歌曲的标签。\u003c/p\u003e\n\u003cp\u003e可以把苹果音乐中的歌当成MP3/320K的音质，因为我上传的无损音乐并没有无损标志。听工友说BSD16bit的音乐和BSD24bit的音乐听起来很不一样，而24bit和32bit的音乐就听不出什么差别。而CD的位数是16bit，再加上压缩编码……因为我听不出MP3/320K和CD格式有什么不同，所以我对这方面倒不是很纠结（主要是莫得钱）。\u003c/p\u003e\n\u003cp\u003e安卓端也有苹果音乐软件……\u003c/p\u003e","title":"我怎么听音乐"},{"content":"明明我应聘的是嵌入式，却要我开发一款ios软件？我以前可是从来都没有碰过苹果系的产品。结果这一趟走下来，从注册公司开发者账号，开发软件，上架商店，也有一些收获。这篇文章主要是一些感想，记下来备忘，也想给一些想做苹果开发者的朋友们一些提示。\n开发者账号 首先是开发者账号，只要是要做ios开发，没有苹果的开发者账号你甚至没办法把程序发出去给别人用。\n开发者账号还有个好处就是可以构建测试版本，通过testflight软件发布的测试版程序根本不需要苹果审核。名额足足有10000人，可以添加appleid自动发送测试邮件，也可以发送公开的邀请链接邀请别人下载安装软件。有些特殊需求的软件甚至不需要发布在app store上，使用人数也没这么多，那么testflight就够用了，不用走审核上架的流程。总之申请账号越早越好。\n申请 开发者账号分公司账号和个人账号，是哪个就申请哪个。申请公司开发者账号麻烦点，我那时候花了3-4天，期间苹果又是给老大打电话，又是给老板打电话确认。我认为苹果是通过这种方式在收集公司信息，真是个可怕的公司。至于申请方法，没什么值得一提的，按照官网流程走就可以了。\n还有一件事，当时我不知道怎么判断账号是否是开发者账号，其实直接上开发者中心登陆账号，如果账号左边的栏目不多，比如没有App Store Connect、Certificates等栏目，就说明还不是开发者账号。我发一张开发者账号的截图出来参考。\n开发 我到处查看资料，发现swift+storyboard的方式最方便合适。然后就是看了几天教程，一步一步把工程搭起来。期间谷歌和苹果开发者平台以及百度（排名分先后）给了很大帮助。\nswfit 学语言就那么一回事，反正也不深入。先看几天基础，比如怎么定义变量，定义函数，条件判断，循环怎么写，内存怎么管理，就可以开始着手了。\nswift的内存管理是计数应用，不知道的可以点进wiki了解一下。因为不够熟练，我在这个地方遇到过问题。将函数内定义的类直接放到后台运行，结果函数一退出，程序就把那个后台就给我GC掉了，当时想了下才发现这个问题。\n对于c/c++出身的我理解那个变量的管理方式有点困难，很是费了一番功夫。比如var s: String?和var s:String的不同之处。印象中这种语法是从c#开始使用的，通过这种方法能有效地避免指针的出现，我认为这是一种很巧妙又优雅的解决方案。\n用过的东西包括定时器、??语法、闭包lambda、还有就是用NSLog替代print，NSLog前面自带时间，调试好用。还有就是直到后来我才发现if没必要写括号，尬住了。\n我一直都没搞懂在引用计数下闭包是怎么管理生命周期的，也没搞懂let到底是怎么区分常量的（类比c中指针const的位置），闭包那奇葩的语法只会用（写是不可能写的……）。总之就是，我又不专门搞苹果开发，学那么多干嘛。\nstoryboard 用swift花不了几天时间，摸索storyboard怎么用和画软件的界面花的时间才多。不过搞熟了之后速度还是很快的，简单明快，拖拖拉拉就完事。我在弄这玩意的时候爽得很，脑子不用动，头发就少掉。\n基本上全部的显示都可以在storyboard中做，绘制页面，页面间的跳转，直接把view拖到page对应的类里面，填上名字就能用。segue给一个唯一名称，在代码里直接就jump。打开storyboard，截屏就是一个软件原型图，不用再搞其它花里胡哨。总之界面开发就一个字，爽。\n这东西没什么可讲的，慢慢摸索就能学会。我没怎么看那些教程（大多都又长又臭），都是一个一个地方点几下，查文档，配合搜索引擎。\n一些废话 百度的苹果开发都是全是基于objc讲的，而且都是前几年的比较多，可能是前几年流行过一阵子的ios开发有关？我读的大学里还有一个专门的苹果机房，听说是前几年配置的。不过配置之后就没开过几门课，我读的时候也没有开，因为根本没人选。就我个人本身而言的话，苹果电脑贵的要命，每年还要几百块的账号注册支出，比我家拉网线还贵，实在是舍不得。而对比国外同事人人一台苹果的情况之下，看来我们还是不够富有啊。\n谷歌搜索出来的信息就全是用swift讲的。从这点可以看出国外的软件开发更加繁荣，个人开发者和小公司开发者很多。因为中小型应用很多，所以对新技术的接受程度普遍而言非常高，软件开发氛围是真正的好。而对比国内，其实可以发现软件公司们就像土地兼并一样，大厂们不断吸收中小软件公司，环境很是恶臭，我觉得这点非常不好。像是以前很好用的快图和天天静听，都是在收购之后销声匿迹了，如果……\n公司配置的二手苹果笔记本好难用，电池还鼓包。这个软件开发历时约两个月，开发效率让我有点惭愧，不过考虑到以前苹果都没摸过，仔细想想也可以接受？还有就是，我好像要一台苹果笔记本！\n上架 上架其实很简单，跟着官方的指示走就行，原则就是把审核员当成客户对待。我开发的是物联网应用，没有产品根本没法用，就一个死页面。不过我准备了产品的官网，产品的介绍PDF，软件使用视频（重要）之后，审核员很快（2天）就给我通过了，通过之后就能在app store上搜索到开发的程序啦😄。\n","permalink":"https://kuang-r.github.io/posts/2021-07-31-%E8%8B%B9%E6%9E%9C%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E4%BA%9B%E6%84%9F%E6%83%B3/","summary":"\u003cp\u003e明明我应聘的是嵌入式，却要我开发一款ios软件？我以前可是从来都没有碰过苹果系的产品。结果这一趟走下来，从注册公司开发者账号，开发软件，上架商店，也有一些收获。这篇文章主要是一些感想，记下来备忘，也想给一些想做苹果开发者的朋友们一些提示。\u003c/p\u003e\n\u003ch2 id=\"开发者账号\"\u003e开发者账号\u003c/h2\u003e\n\u003cp\u003e首先是开发者账号，只要是要做ios开发，没有苹果的开发者账号你甚至没办法把程序发出去给别人用。\u003c/p\u003e\n\u003cp\u003e开发者账号还有个好处就是可以构建测试版本，通过testflight软件发布的测试版程序根本不需要苹果审核。名额足足有10000人，可以添加appleid自动发送测试邮件，也可以发送公开的邀请链接邀请别人下载安装软件。有些特殊需求的软件甚至不需要发布在app store上，使用人数也没这么多，那么testflight就够用了，不用走审核上架的流程。总之申请账号越早越好。\u003c/p\u003e\n\u003ch3 id=\"申请\"\u003e申请\u003c/h3\u003e\n\u003cp\u003e开发者账号分公司账号和个人账号，是哪个就申请哪个。申请公司开发者账号麻烦点，我那时候花了3-4天，期间苹果又是给老大打电话，又是给老板打电话确认。我认为苹果是通过这种方式在收集公司信息，真是个可怕的公司。至于申请方法，没什么值得一提的，按照官网流程走就可以了。\u003c/p\u003e\n\u003cp\u003e还有一件事，当时我不知道怎么判断账号是否是开发者账号，其实直接上\u003ca href=\"https://developer.apple.com/\"\u003e开发者中心\u003c/a\u003e登陆账号，如果账号左边的栏目不多，比如没有App Store Connect、Certificates等栏目，就说明还不是开发者账号。我发一张开发者账号的截图出来参考。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"开发者账号截图\" loading=\"lazy\" src=\"/imgs/210731-01.jpg\"\u003e\u003c/p\u003e\n\u003ch2 id=\"开发\"\u003e开发\u003c/h2\u003e\n\u003cp\u003e我到处查看资料，发现swift+storyboard的方式最方便合适。然后就是看了几天教程，一步一步把工程搭起来。期间谷歌和苹果开发者平台以及百度（排名分先后）给了很大帮助。\u003c/p\u003e\n\u003ch3 id=\"swfit\"\u003eswfit\u003c/h3\u003e\n\u003cp\u003e学语言就那么一回事，反正也不深入。先看几天基础，比如怎么定义变量，定义函数，条件判断，循环怎么写，内存怎么管理，就可以开始着手了。\u003c/p\u003e\n\u003cp\u003eswift的内存管理是\u003ca href=\"https://zh.wikipedia.org/wiki/%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0\"\u003e计数应用\u003c/a\u003e，不知道的可以点进wiki了解一下。因为不够熟练，我在这个地方遇到过问题。将函数内定义的类直接放到后台运行，结果函数一退出，程序就把那个后台就给我GC掉了，当时想了下才发现这个问题。\u003c/p\u003e\n\u003cp\u003e对于c/c++出身的我理解那个变量的管理方式有点困难，很是费了一番功夫。比如\u003ccode\u003evar s: String?\u003c/code\u003e和\u003ccode\u003evar s:String\u003c/code\u003e的不同之处。印象中这种语法是从c#开始使用的，通过这种方法能有效地避免指针的出现，我认为这是一种很巧妙又优雅的解决方案。\u003c/p\u003e\n\u003cp\u003e用过的东西包括定时器、??语法、闭包lambda、还有就是用NSLog替代print，NSLog前面自带时间，调试好用。还有就是直到后来我才发现if没必要写括号，尬住了。\u003c/p\u003e\n\u003cp\u003e我一直都没搞懂在引用计数下闭包是怎么管理生命周期的，也没搞懂let到底是怎么区分常量的（类比c中指针const的位置），闭包那奇葩的语法只会用（写是不可能写的……）。总之就是，我又不专门搞苹果开发，学那么多干嘛。\u003c/p\u003e\n\u003ch3 id=\"storyboard\"\u003estoryboard\u003c/h3\u003e\n\u003cp\u003e用swift花不了几天时间，摸索storyboard怎么用和画软件的界面花的时间才多。不过搞熟了之后速度还是很快的，简单明快，拖拖拉拉就完事。我在弄这玩意的时候爽得很，脑子不用动，头发就少掉。\u003c/p\u003e\n\u003cp\u003e基本上全部的显示都可以在storyboard中做，绘制页面，页面间的跳转，直接把view拖到page对应的类里面，填上名字就能用。segue给一个唯一名称，在代码里直接就jump。打开storyboard，截屏就是一个软件原型图，不用再搞其它花里胡哨。总之界面开发就一个字，爽。\u003c/p\u003e\n\u003cp\u003e这东西没什么可讲的，慢慢摸索就能学会。我没怎么看那些教程（大多都又长又臭），都是一个一个地方点几下，查文档，配合搜索引擎。\u003c/p\u003e\n\u003ch3 id=\"一些废话\"\u003e一些废话\u003c/h3\u003e\n\u003cp\u003e百度的苹果开发都是全是基于objc讲的，而且都是前几年的比较多，可能是前几年流行过一阵子的ios开发有关？我读的大学里还有一个专门的苹果机房，听说是前几年配置的。不过配置之后就没开过几门课，我读的时候也没有开，因为根本没人选。就我个人本身而言的话，苹果电脑贵的要命，每年还要几百块的账号注册支出，比我家拉网线还贵，实在是舍不得。而对比国外同事人人一台苹果的情况之下，看来我们还是不够富有啊。\u003c/p\u003e\n\u003cp\u003e谷歌搜索出来的信息就全是用swift讲的。从这点可以看出国外的软件开发更加繁荣，个人开发者和小公司开发者很多。因为中小型应用很多，所以对新技术的接受程度普遍而言非常高，软件开发氛围是真正的好。而对比国内，其实可以发现软件公司们就像土地兼并一样，大厂们不断吸收中小软件公司，环境很是恶臭，我觉得这点非常不好。像是以前很好用的快图和天天静听，都是在收购之后销声匿迹了，如果……\u003c/p\u003e\n\u003cp\u003e公司配置的二手苹果笔记本好难用，电池还鼓包。这个软件开发历时约两个月，开发效率让我有点惭愧，不过考虑到以前苹果都没摸过，仔细想想也可以接受？还有就是，我好像要一台苹果笔记本！\u003c/p\u003e\n\u003ch2 id=\"上架\"\u003e上架\u003c/h2\u003e\n\u003cp\u003e上架其实很简单，跟着官方的指示走就行，原则就是把审核员当成客户对待。我开发的是物联网应用，没有产品根本没法用，就一个死页面。不过我准备了产品的官网，产品的介绍PDF，软件使用视频（重要）之后，审核员很快（2天）就给我通过了，通过之后就能在app store上搜索到开发的程序啦😄。\u003c/p\u003e","title":"苹果开发的一些感想"},{"content":"习惯了Posix环境下的各种方便工具，就很难在Windows平台下得到较好的编程体验。而在当前国内的网络环境下，直接使用Linux系统又有极大的不便之处。再加上Windows平台上又有很多软件没办法舍弃，所以我一直在寻找一种替代方案：在Windows上安装Posix环境。\nPosix环境 编程环境总共就两家，Windows和Unix。上个世纪出现了很多Unix系统，使用上分化很严重。尽管都是叫Unix，但它们的兼容性没法保障。比如我在这台机器上写的程序，在另一台机器上甚至没法编译通过！后来就出现了Posix标准，符合这个标准的才给叫Unix。这下好了，我们写的程序不需要一个一个系统地测试了。\n最热门的Linux系统属于类Unix系统，用起来一般不会出现跟Posix标准不符合的情况（反正我没见过）。所以大多数说的Linux编程大致等于Unix编程。\n在Windows上提供Posix环境操作的主要有两家，msys2和wsl2。\nwsl2 我没用过wsl2，不过听说wsl2用的是虚拟化技术，效率上就低了一层。再加上又是个新东西，稳定性肯定欠缺。而且还是微软推的技术，殊不知之前的wsl还没用几天呢，这就wsl2了？说不定明天微软就不爱Linux了。那我岂不哭死？\nmsys2 msys2就好多了，社区推动不会突然间就暴死，更新稳定性更有保障。在国内也有专门的镜像源（你甚至不需要做任何的配置），上清华软件站下载打包好的安装包一键安装就可以了。配有专门的软件包管理工具pacman，安装卸载软件包一键搞定。还可以通过配置注册表在文件夹下右键打开终端，获取跟Linux一样的体验。\n我对它唯一的不满就是这终端界面，也太丑了。不过我都懒得去美化它，麻烦不说，稳定性就没法保障。尽量保持默认配置，是我稳定使用工具软件的诀窍。\n所以终极方案就是Windows10+msys2+虚拟机。为什么还需要虚拟机呢？有时候一些东西实在是没法在Windows系统上搞的（比如ROS），就只能装个虚拟机勉强用着了。\nmsys2配置 如何添加右键打开，软件包管理工具的简单使用。\n添加右键菜单 打开注册表HKEY_CLASSES_ROOT\\Directory\\Background\\shell 新建项msys2，默认值修改为msys2 新建字符串值，命名为icon，修改值为C:\\msys64\\msys2.icon 修改command的默认值为C:\\msys64\\msys2_shell.cmd -mingw64 -here 软件包工具pacman pacman 其实是arch项目的软件包管理工具，与arch通用\n{% highlight sh %} pacman -Ss qt6 # 搜索软件包 pacman -S mingw-w64-x86_64-qt6 # 安装qt6 pacman -R mingw-w64-x86_64-qt6 # 删除qt6 pacman -Q # 列出已安装的软件包 {% endhighlight %}\n安装环境的选择 搜索软件包之后发现很多不同前缀的软件包。\n分别是mingw32, mingw64, ucrt64, clang64, msys。这些前缀分别对应各个不同的运行环境。从msys2的根目录可以看出，里面有对应前缀的可执行文件，分别对应不同的执行环境。我习惯使用mingw64环境，一直都没出现过什么问题，所以我也推荐你使用这个环境。\n在安装时选择对应环境的安装包，然后在相应环境打开的shell中就可以使用。比如你安装了clang64的软件，就只有在打开clang64.exe的终端中才能使用软件，在其它环境中是搜索不到的。\n注意到上面右键打开终端菜单设置中打开的是ming64环境。 在使用软件包工具时我安装的也是mingw64的软件包。\n","permalink":"https://kuang-r.github.io/posts/2021-07-26-%E7%BC%96%E7%A8%8B%E7%8E%AF%E5%A2%83%E7%BB%88%E6%9E%81%E9%85%8D%E7%BD%AE/","summary":"\u003cp\u003e习惯了Posix环境下的各种方便工具，就很难在Windows平台下得到较好的编程体验。而在当前国内的网络环境下，直接使用Linux系统又有极大的不便之处。再加上Windows平台上又有很多软件没办法舍弃，所以我一直在寻找一种替代方案：在Windows上安装Posix环境。\u003c/p\u003e\n\u003ch2 id=\"posix环境\"\u003ePosix环境\u003c/h2\u003e\n\u003cp\u003e编程环境总共就两家，Windows和Unix。上个世纪出现了很多Unix系统，使用上分化很严重。尽管都是叫Unix，但它们的兼容性没法保障。比如我在这台机器上写的程序，在另一台机器上甚至没法编译通过！后来就出现了Posix标准，符合这个标准的才给叫Unix。这下好了，我们写的程序不需要一个一个系统地测试了。\u003c/p\u003e\n\u003cp\u003e最热门的Linux系统属于类Unix系统，用起来一般不会出现跟Posix标准不符合的情况（反正我没见过）。所以大多数说的Linux编程大致等于Unix编程。\u003c/p\u003e\n\u003cp\u003e在Windows上提供Posix环境操作的主要有两家，msys2和wsl2。\u003c/p\u003e\n\u003ch3 id=\"wsl2\"\u003ewsl2\u003c/h3\u003e\n\u003cp\u003e我没用过wsl2，不过听说wsl2用的是虚拟化技术，效率上就低了一层。再加上又是个新东西，稳定性肯定欠缺。而且还是微软推的技术，殊不知之前的wsl还没用几天呢，这就wsl2了？说不定明天微软就不爱Linux了。那我岂不哭死？\u003c/p\u003e\n\u003ch3 id=\"msys2\"\u003emsys2\u003c/h3\u003e\n\u003cp\u003emsys2就好多了，社区推动不会突然间就暴死，更新稳定性更有保障。在国内也有专门的镜像源（你甚至不需要做任何的配置），上\u003ca href=\"https://mirrors.tuna.tsinghua.edu.cn/\"\u003e清华软件站\u003c/a\u003e下载打包好的安装包一键安装就可以了。配有专门的软件包管理工具pacman，安装卸载软件包一键搞定。还可以通过配置注册表在文件夹下右键打开终端，获取跟Linux一样的体验。\u003c/p\u003e\n\u003cp\u003e我对它唯一的不满就是这终端界面，也太丑了。不过我都懒得去美化它，麻烦不说，稳定性就没法保障。尽量保持默认配置，是我稳定使用工具软件的诀窍。\u003c/p\u003e\n\u003cp\u003e所以终极方案就是Windows10+msys2+虚拟机。为什么还需要虚拟机呢？有时候一些东西实在是没法在Windows系统上搞的（比如ROS），就只能装个虚拟机勉强用着了。\u003c/p\u003e\n\u003ch2 id=\"msys2配置\"\u003emsys2配置\u003c/h2\u003e\n\u003cp\u003e如何添加右键打开，软件包管理工具的简单使用。\u003c/p\u003e\n\u003ch3 id=\"添加右键菜单\"\u003e添加右键菜单\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e打开注册表\u003ccode\u003eHKEY_CLASSES_ROOT\\Directory\\Background\\shell\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e新建项\u003ccode\u003emsys2\u003c/code\u003e，默认值修改为\u003ccode\u003emsys2\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e新建字符串值，命名为\u003ccode\u003eicon\u003c/code\u003e，修改值为\u003ccode\u003eC:\\msys64\\msys2.icon\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e修改command的默认值为\u003ccode\u003eC:\\msys64\\msys2_shell.cmd -mingw64 -here\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"软件包工具pacman\"\u003e软件包工具pacman\u003c/h3\u003e\n\u003cp\u003epacman 其实是arch项目的软件包管理工具，与arch通用\u003c/p\u003e\n\u003cp\u003e{% highlight sh %}\npacman -Ss qt6 # 搜索软件包\npacman -S mingw-w64-x86_64-qt6 # 安装qt6\npacman -R mingw-w64-x86_64-qt6 # 删除qt6\npacman -Q  # 列出已安装的软件包\n{% endhighlight %}\u003c/p\u003e\n\u003ch3 id=\"安装环境的选择\"\u003e安装环境的选择\u003c/h3\u003e\n\u003cp\u003e搜索软件包之后发现很多不同前缀的软件包。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"搜索截图\" loading=\"lazy\" src=\"/imgs/210726-01.png\"\u003e\u003c/p\u003e\n\u003cp\u003e分别是\u003ccode\u003emingw32\u003c/code\u003e, \u003ccode\u003emingw64\u003c/code\u003e, \u003ccode\u003eucrt64\u003c/code\u003e, \u003ccode\u003eclang64\u003c/code\u003e, \u003ccode\u003emsys\u003c/code\u003e。这些前缀分别对应各个不同的运行环境。从msys2的根目录可以看出，里面有对应前缀的可执行文件，分别对应不同的执行环境。我习惯使用mingw64环境，一直都没出现过什么问题，所以我也推荐你使用这个环境。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"msys2根目录\" loading=\"lazy\" src=\"/imgs/210726-02.png\"\u003e\u003c/p\u003e\n\u003cp\u003e在安装时选择对应环境的安装包，然后在相应环境打开的shell中就可以使用。比如你安装了clang64的软件，就只有在打开clang64.exe的终端中才能使用软件，在其它环境中是搜索不到的。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e注意到上面右键打开终端菜单设置中打开的是ming64环境。\n在使用软件包工具时我安装的也是mingw64的软件包。\u003c/p\u003e\n\u003c/blockquote\u003e","title":"编程环境终极配置"},{"content":"尽量使用#define代替enum 因为枚举常量的标识符与变量和typedef名称属于同一个重载分类。 声明会被覆盖\n区分字符型和整型 在进行嵌入式通信编程时，很多人都不搞不清楚字符型和整型之间的区别。 这应该从这两种类型的存储形式和表现形式来区分。\n字符型底层存储形式一般是ascii码，一个signed char的正数足够表示所有的ascii字符。 表现形式是单个字符。\n整型的底层存储形式一般是补码，大小范围取决于具体的类型和占用的字节数。 表现形式通过printf系函数显示出来。\n指针的const使用 const指针有两种方式。\n在*之前加const表示指向的值不能变。\n在*之后加const表示指针本身不能变。\n宏的一些使用 将标识符转为字符串，自动转义和加括号。\n1 #define TEST(a, b) printf(#a \u0026#34;\u0026lt;\u0026#34; #b) 标记合并\n1 2 #define fun(i) fun ## i // fun(1) 转换为 fun1 ","permalink":"https://kuang-r.github.io/posts/2021-01-26-c/","summary":"\u003ch2 id=\"尽量使用define代替enum\"\u003e尽量使用#define代替enum\u003c/h2\u003e\n\u003cp\u003e因为枚举常量的标识符与变量和typedef名称属于同一个重载分类。\n声明会被覆盖\u003c/p\u003e\n\u003ch2 id=\"区分字符型和整型\"\u003e区分字符型和整型\u003c/h2\u003e\n\u003cp\u003e在进行嵌入式通信编程时，很多人都不搞不清楚字符型和整型之间的区别。\n这应该从这两种类型的存储形式和表现形式来区分。\u003c/p\u003e\n\u003cp\u003e字符型底层存储形式一般是ascii码，一个signed char的正数足够表示所有的ascii字符。\n表现形式是单个字符。\u003c/p\u003e\n\u003cp\u003e整型的底层存储形式一般是补码，大小范围取决于具体的类型和占用的字节数。\n表现形式通过printf系函数显示出来。\u003c/p\u003e\n\u003ch2 id=\"指针的const使用\"\u003e指针的const使用\u003c/h2\u003e\n\u003cp\u003econst指针有两种方式。\u003c/p\u003e\n\u003cp\u003e在*之前加const表示指向的值不能变。\u003c/p\u003e\n\u003cp\u003e在*之后加const表示指针本身不能变。\u003c/p\u003e\n\u003ch2 id=\"宏的一些使用\"\u003e宏的一些使用\u003c/h2\u003e\n\u003cp\u003e将标识符转为字符串，自动转义和加括号。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define TEST(a, b) printf(#a \u0026#34;\u0026lt;\u0026#34; #b)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e标记合并\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define fun(i) fun ## i\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// fun(1) 转换为 fun1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"c"},{"content":"bashrc 1 2 # terminal color export PS1=\u0026#39;[\\[\\e[01;32m\\]\\u@\\h\\[\\e[00m\\] \\[\\e[01;34m\\]\\W\\[\\e[00m\\]]\\$ \u0026#39; 重定向 1 2 cmd $\u0026gt;output.txt cmd |tee file1 |cmd 子shell 1 2 3 # cat files.txt |xargs -I {} cat {} cat files.txt | (while read args; do cat $arg; done) cmd0 |(cd path;cmd1;cmd2) |cmd3 各种命令 seq 0 100返回0到100的整数，分隔符为换行 数值比较用[]，字符串比较用[[]] 内建功能 变量 作用 $0 脚本名称 $@ \u0026ldquo;$1\u0026rdquo; \u0026ldquo;$2\u0026rdquo; \u0026ldquo;$3\u0026rdquo; $* \u0026ldquo;$1c$2c$3\u0026rdquo; $? 上一个命令退出状态 IFS 分隔符集合 c表示INS的第一个字符\n1 2 3 4 5 length=${#var} #获取字符串长度 echo ${array_var[*]} #打印数组所有值 declare -A arr #定义关联数组 echo ${!arr[*]} #列出关联数组索引 $(cd /bin; ls) #子shell比反引用更好 数学运算（整数）\n1 2 3 let result=no1+no2 result=$[ no1 + no2] result=$(( no1 + no2)) 数学运算（高级）\n1 2 3 4 result=`echo \u0026#34;$no * 1.5\u0026#34; |bc` result=`echo \u0026#34;scale=2;22/7\u0026#34; |bc` #设定浮点数精度 result=`echo \u0026#34;obase=G;ibase=A;$no\u0026#34; |bc` #16进制转10进制 result=`echo \u0026#34;scale=2;sqrt(88)` 常用代码块 遍历带空格参数\n1 2 3 4 while test -n \u0026#34;${1}\u0026#34;; do \u0026#34; do something shift 1 done {name%.*}，%删除右边非贪婪匹配的部分，返回去除后缀的文件名\n{name##*.}，##删除左边贪婪匹配的部分，返回文件名后缀\n","permalink":"https://kuang-r.github.io/posts/2021-01-17-shell/","summary":"\u003ch2 id=\"bashrc\"\u003ebashrc\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# terminal color\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport PS1\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;[\\[\\e[01;32m\\]\\u@\\h\\[\\e[00m\\] \\[\\e[01;34m\\]\\W\\[\\e[00m\\]]\\$ \u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"重定向\"\u003e重定向\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmd $\u0026gt;output.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmd |tee file1 |cmd\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"子shell\"\u003e子shell\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# cat files.txt |xargs -I {} cat {}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecat files.txt | \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e read args; \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e cat $arg; \u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmd0 |\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ecd path;cmd1;cmd2\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e |cmd3\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"各种命令\"\u003e各种命令\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eseq 0 100\u003c/code\u003e返回0到100的整数，分隔符为换行\u003c/li\u003e\n\u003cli\u003e数值比较用[]，字符串比较用[[]]\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"内建功能\"\u003e内建功能\u003c/h2\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e变量\u003c/th\u003e\n          \u003cth\u003e作用\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e$0\u003c/td\u003e\n          \u003ctd\u003e脚本名称\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e$@\u003c/td\u003e\n          \u003ctd\u003e\u0026ldquo;$1\u0026rdquo; \u0026ldquo;$2\u0026rdquo; \u0026ldquo;$3\u0026rdquo;\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e$*\u003c/td\u003e\n          \u003ctd\u003e\u0026ldquo;$1c$2c$3\u0026rdquo;\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e$?\u003c/td\u003e\n          \u003ctd\u003e上一个命令退出状态\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eIFS\u003c/td\u003e\n          \u003ctd\u003e分隔符集合\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003ec表示INS的第一个字符\u003c/p\u003e","title":"terminal color"},{"content":"命令 一些常用命令的使用方式和选项\nfind -name -iname 否定加! find . ! -name '*.txt' -o -a find . \\( -name '*.txt' -o '*.png' \\) -path find . -path '*/slynux/*' -name '*.txt' -maxdepth -mindepth find -maxdepth 1 -name '*.txt' -L 跟随符号链接 -type 文件类型 -size find . -size +2k -user find . -user slynux 时间戳 -atime 最后一次访问 -mtime 最后一次修改 -ctime 元数据（权限或所有权）最后一次改变 -mmin 分钟 1 2 # 1天前，7天内修改的文件 find . -mtime -7 -mtime +1 xargs 从标准输入中读取数据，转换为另一个命令的参数输入。默认会执行echo指令。\n-d 分隔符 echo \u0026quot;123X456X789\u0026quot; |xargs -d X -n 1 -n 每次调用命令的参数个数 printf \u0026quot;1 2 3\\n4 5 6\\n7 8\u0026quot; |xargs -n 3 -I {} 用{}代替字符串，默认带有-n 1 echo \u0026quot;1 2\u0026quot; |xargs -d\u0026quot; \u0026quot; -I {} echo {} 1 find . -print0 |xargs -0 tr -d delete -c 补集 tr -d -c '0-9' -s 删除重复字符 tr -s '\\n' 1 2 3 4 5 6 printf \u0026#39;1 2 3 4 5 \u0026#39; |echo $[ $(tr \u0026#39; \u0026#39; \u0026#39;+\u0026#39;) 0 ] ## md5sum ``` sh md5sum * \u0026gt;file_sum.md5 md5sum -c file_sum.md5 gpg 查看详细\nsort uniq sort -n 数字排序 -r 逆序排序 -k 选择列号 -b 忽略前导空白 -C 验证是否已排序 if sort -C file; then echo sorted; fi uniq -u 输出唯一的行 -d 输出重复的行 -c 统计次数 -z 以\\0作为分隔符输出 mktemp -d 创建目录 -u 只生成文件名，不创建 ivonv 1 2 # 日文转utf-8 iconv -c -f SHIFT-JIS -t utf-8 filename midecode 用于查看硬件信息\n","permalink":"https://kuang-r.github.io/posts/2021-01-17-posix-command/","summary":"\u003ch1 id=\"命令\"\u003e命令\u003c/h1\u003e\n\u003cp\u003e一些常用命令的使用方式和选项\u003c/p\u003e\n\u003ch2 id=\"find\"\u003efind\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e-name -iname 否定加! \u003ccode\u003efind . ! -name '*.txt'\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e-o -a \u003ccode\u003efind . \\( -name '*.txt' -o '*.png' \\)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e-path \u003ccode\u003efind . -path '*/slynux/*' -name '*.txt'\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e-maxdepth -mindepth \u003ccode\u003efind -maxdepth 1 -name '*.txt'\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e-L 跟随符号链接\u003c/li\u003e\n\u003cli\u003e-type 文件类型\u003c/li\u003e\n\u003cli\u003e-size \u003ccode\u003efind . -size +2k\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e-user \u003ccode\u003efind . -user slynux\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"时间戳\"\u003e时间戳\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e-atime 最后一次访问\u003c/li\u003e\n\u003cli\u003e-mtime 最后一次修改\u003c/li\u003e\n\u003cli\u003e-ctime 元数据（权限或所有权）最后一次改变\u003c/li\u003e\n\u003cli\u003e-mmin 分钟\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 1天前，7天内修改的文件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efind . -mtime -7 -mtime +1\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"xargs\"\u003exargs\u003c/h2\u003e\n\u003cp\u003e从标准输入中读取数据，转换为另一个命令的参数输入。默认会执行\u003ccode\u003eecho\u003c/code\u003e指令。\u003c/p\u003e","title":"命令"},{"content":"综述 jekyll是一个静态页面生成的框架，功能很强大。一个典型的例子是它的官网和gtk的官网。 但是我在学这东西的时候却感到很头疼，一方面是这个工具是使用ruby的包管理器管理组件，我对ruby是一窍不通。 另一方面是它的官网虽然做得很好看，但是这文档写得也太简陋了，对于没有前端基础的人来说简直一头雾水。 还有一个问题是它标配的主题minima在本地服务器时是正常的，build出来的页面却不正常。连官方主题都是这样，其它的主题也就可想而知了。\n包管理的问题可以用fedora的dnf解决，主题的问题干脆学个前端框架算了。就选bootstrap吧，它最多人用。\n_config.yml 1 2 3 4 5 6 # 用github的markdown语法 kramdown: input: GFM auto_ids: true hard_wrap: false syntax_highlighter: rouge ","permalink":"https://kuang-r.github.io/posts/2021-01-16-jekyll/","summary":"\u003ch2 id=\"综述\"\u003e综述\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003ejekyll\u003c/code\u003e是一个静态页面生成的框架，功能很强大。一个典型的例子是它的\u003ca href=\"https://jekyllrb.com/\"\u003e官网\u003c/a\u003e和gtk的\u003ca href=\"https://gtk.org/\"\u003e官网\u003c/a\u003e。\n但是我在学这东西的时候却感到很头疼，一方面是这个工具是使用ruby的包管理器管理组件，我对ruby是一窍不通。\n另一方面是它的官网虽然做得很好看，但是这文档写得也太简陋了，对于没有前端基础的人来说简直一头雾水。\n还有一个问题是它标配的主题minima在本地服务器时是正常的，build出来的页面却不正常。连官方主题都是这样，其它的主题也就可想而知了。\u003c/p\u003e\n\u003cp\u003e包管理的问题可以用fedora的dnf解决，主题的问题干脆学个前端框架算了。就选\u003ccode\u003ebootstrap\u003c/code\u003e吧，它最多人用。\u003c/p\u003e\n\u003ch2 id=\"_configyml\"\u003e_config.yml\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e6\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yml\" data-lang=\"yml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 用github的markdown语法\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ekramdown\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eGFM\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eauto_ids\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ehard_wrap\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003esyntax_highlighter\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003erouge\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"用github的markdown语法"},{"content":"键盘映射（cpas与ctrl互换） 由于之前有一段时间学习vim，我已经习惯这种键盘映射。\n在不同的系统上有不同的方法。Windows系统需要修改注册表；Linux系统有两种方法修改；Mac系统可以直接在系统设置里调整。\nwindows系统修改方法 输入regetdit打开注册表，找到对应的项\n新建二进制值，重命名为Scancode Map，并修改为下图\n**重启电脑后才会生效\nLinux系统修改方法：xorg 首先确保系统里有安装xmodmap这个软件，然后在家目录下创建.Xmodmap文件即可。\n1 2 3 4 5 6 7 8 9 ! ! Swap Caps_Lock and Control_L ! remove Lock = Caps_Lock remove Control = Control_L keysym Control_L = Caps_Lock keysym Caps_Lock = Control_L add Lock = Caps_Lock add Control = Control_L 一般而言安装xmodmap软件后会附带地安装自动运行脚本，但是也有没安装的情况。这个时候如果重启后不生效，就需要自己写脚本，设置进入桌面时自动启动xmodmap修改映射，在~/.config/autostart/目录下创建modmap.desktop。\n1 2 3 4 5 [Desktop Entry] Name=modmap Exec=xmodmap ~/.Xmodmap Terminal=false Type=Application Linux系统修改方法：wayland 在上一个方法不起作用的时候用这个。\n直接修改/usr/share/X11/xkb/symbols/pc文件\n1 2 key \u0026lt;CAPS\u0026gt; {\t[ Control_L\t]\t}; key \u0026lt;LCTL\u0026gt; {\t[ Caps_Lock\t]\t}; ","permalink":"https://kuang-r.github.io/posts/2021-01-14-%E9%94%AE%E7%9B%98%E6%98%A0%E5%B0%84/","summary":"\u003ch1 id=\"键盘映射cpas与ctrl互换\"\u003e键盘映射（cpas与ctrl互换）\u003c/h1\u003e\n\u003chr\u003e\n\u003cp\u003e由于之前有一段时间学习vim，我已经习惯这种键盘映射。\u003c/p\u003e\n\u003cp\u003e在不同的系统上有不同的方法。Windows系统需要修改注册表；Linux系统有两种方法修改；Mac系统可以直接在系统设置里调整。\u003c/p\u003e\n\u003ch2 id=\"windows系统修改方法\"\u003ewindows系统修改方法\u003c/h2\u003e\n\u003cp\u003e\u003cWin-R\u003e输入\u003ccode\u003eregetdit\u003c/code\u003e打开注册表，找到对应的项\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"picture1\" loading=\"lazy\" src=\"/imgs/2021-01-14-%E6%8C%89%E9%94%AE%E6%98%A0%E5%B0%8401.png\"\u003e\u003c/p\u003e\n\u003cp\u003e新建二进制值，重命名为\u003ccode\u003eScancode Map\u003c/code\u003e，并修改为下图\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"picture2\" loading=\"lazy\" src=\"/imgs/2021-01-14-%E6%8C%89%E9%94%AE%E6%98%A0%E5%B0%8402.png\"\u003e\u003c/p\u003e\n\u003cp\u003e**重启电脑后才会生效\u003c/p\u003e\n\u003ch2 id=\"linux系统修改方法xorg\"\u003eLinux系统修改方法：xorg\u003c/h2\u003e\n\u003cp\u003e首先确保系统里有安装xmodmap这个软件，然后在家目录下创建.Xmodmap文件即可。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e8\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e9\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e!\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e! Swap Caps_Lock and Control_L\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e!\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremove Lock = Caps_Lock\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremove Control = Control_L\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekeysym Control_L = Caps_Lock\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ekeysym Caps_Lock = Control_L\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadd Lock = Caps_Lock\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadd Control = Control_L\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e一般而言安装xmodmap软件后会附带地安装自动运行脚本，但是也有没安装的情况。这个时候如果重启后不生效，就需要自己写脚本，设置进入桌面时自动启动xmodmap修改映射，在\u003ccode\u003e~/.config/autostart/\u003c/code\u003e目录下创建modmap.desktop。\u003c/p\u003e","title":"键盘映射（cpas与ctrl互换）"},{"content":"gnu binutils 一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。是UNIX系统实验室（USL）作为应用程序二进制接口（Application Binary Interface，ABI）而开发和发布的，也是Linux的主要可执行文件格式。\ngcc -g 设置为gdb可使用可执行文件 -E 预处理 -S 编译为汇编代码 -c 编译为目标文件 -o 输出的文件名称 gdb l 列出代码 break+行号 设置断点 break+函数 info break 查看断点信息 r 运行程序 n 单步执行 p 输出变量 c 继续运行直到下一个断点 debug 函数运行时间与调用次数 1 2 3 gcc -o test test.c -g -pg ./test # 运行完后会生成gmon.out文件 gprof test # 实现依赖于unix信号量 行计数 1 2 3 gcc -o test test.c -fprofile-arcs -ftest-coverage ./test gcov test # 生成.gcov文件 ","permalink":"https://kuang-r.github.io/posts/2021-01-13-gcc/","summary":"\u003ch2 id=\"gnu-binutils\"\u003egnu binutils\u003c/h2\u003e\n\u003cp\u003e一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。是UNIX系统实验室（USL）作为应用程序二进制接口（Application Binary Interface，ABI）而开发和发布的，也是Linux的主要可执行文件格式。\u003c/p\u003e\n\u003ch2 id=\"gcc\"\u003egcc\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e-g 设置为gdb可使用可执行文件\u003c/li\u003e\n\u003cli\u003e-E 预处理\u003c/li\u003e\n\u003cli\u003e-S 编译为汇编代码\u003c/li\u003e\n\u003cli\u003e-c 编译为目标文件\u003c/li\u003e\n\u003cli\u003e-o 输出的文件名称\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"gdb\"\u003egdb\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003el 列出代码\u003c/li\u003e\n\u003cli\u003ebreak+行号 设置断点\u003c/li\u003e\n\u003cli\u003ebreak+函数\u003c/li\u003e\n\u003cli\u003einfo break 查看断点信息\u003c/li\u003e\n\u003cli\u003er 运行程序\u003c/li\u003e\n\u003cli\u003en 单步执行\u003c/li\u003e\n\u003cli\u003ep 输出变量\u003c/li\u003e\n\u003cli\u003ec 继续运行直到下一个断点\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"debug\"\u003edebug\u003c/h2\u003e\n\u003ch3 id=\"函数运行时间与调用次数\"\u003e函数运行时间与调用次数\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egcc -o test test.c -g -pg\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./test # 运行完后会生成gmon.out文件\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egprof test # 实现依赖于unix信号量\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch3 id=\"行计数\"\u003e行计数\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egcc -o test test.c -fprofile-arcs -ftest-coverage\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./test\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egcov test # 生成.gcov文件\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"gcc"},{"content":"系统维护 硬盘 1 2 fdisk -l\t#列出硬盘分区 blkid\t#查看硬盘id grub2 1 2 3 4 5 6 7 8 9 #记住最后选项 ### 创建虚拟终端 ``` sh socat -d -d PTY PTY sudo vim /etc/default/grub GRUB_DEFAULT=saved GRUB_SAVEDEFAULT=true sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg 操作串口 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include \u0026lt;sys/types.h\u0026gt; #include \u0026lt;sys/stat.h\u0026gt; #include \u0026lt;fcntl.h\u0026gt; #include \u0026lt;unistd.h\u0026gt; #include \u0026lt;termios.h\u0026gt; #include \u0026lt;stdio.h\u0026gt; int main() { size_t buf_len; char buf[512]; int fd = open(\u0026#34;/dev/pts/5\u0026#34;, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) return -1; struct termios tio; if (tcgetattr(fd, \u0026amp;tio) != 0) return -2; tio.c_cflag |= CLOCAL; // 保证程序不占用串口 tio.c_cflag |= CREAD; // 使能读数据 tio.c_cflag \u0026amp;= ~CRTSCTS; // 不使用流控制 tio.c_cflag \u0026amp;= ~CSIZE; // 屏蔽其它标志位 tio.c_cflag |= CS8; // 8位数据位 tio.c_cflag \u0026amp;= ~PARENB; // 无奇偶校验 tio.c_iflag \u0026amp;= ~INPCK; tio.c_cflag \u0026amp;= ~CSTOPB; // 1位停止位 tio.c_oflag \u0026amp;= ~OPOST; // 原始数据输出 tio.c_lflag \u0026amp;= ~(ICANON | ECHO | ECHOE | ISIG); if (cfsetspeed(\u0026amp;tio, B115200) != 0) return -3; if (tcsetattr(fd, TCSANOW, \u0026amp;tio) != 0) return -4; for (int i = 0; i \u0026lt; 100; ++i) write(fd, \u0026#34;1234\u0026#34;, 4); while (1) { printf(\u0026#34;ok\\n\u0026#34;); if ((buf_len = read(fd, buf, 512)) != -1) { for (int i = 0; i \u0026lt; buf_len; ++i) printf(\u0026#34;%c\u0026#34;, buf[i]); } sleep(1); } } ","permalink":"https://kuang-r.github.io/posts/2021-01-13-posix/","summary":"\u003ch2 id=\"系统维护\"\u003e系统维护\u003c/h2\u003e\n\u003ch3 id=\"硬盘\"\u003e硬盘\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efdisk -l\t\u003cspan style=\"color:#75715e\"\u003e#列出硬盘分区\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eblkid\t\t\u003cspan style=\"color:#75715e\"\u003e#查看硬盘id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch3 id=\"grub2\"\u003egrub2\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e8\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e9\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#记住最后选项\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e### 创建虚拟终端\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e```\u003c/span\u003e sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esocat -d -d PTY PTY\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo vim /etc/default/grub\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGRUB_DEFAULT\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003esaved\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGRUB_SAVEDEFAULT\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etrue\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"操作串口\"\u003e操作串口\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 8\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e 9\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e10\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e11\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e12\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e13\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e14\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e15\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e16\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e17\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e18\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e19\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e20\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e21\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e22\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e23\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e24\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e25\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e26\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e27\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e28\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e29\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e30\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e31\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e32\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e33\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e34\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e35\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e36\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e37\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e38\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e39\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e40\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e41\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e42\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e43\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e44\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e45\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e46\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e47\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-C\" data-lang=\"C\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;sys/types.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;sys/stat.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;fcntl.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;unistd.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;termios.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;stdio.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003esize_t\u003c/span\u003e buf_len;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e buf[\u003cspan style=\"color:#ae81ff\"\u003e512\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e fd \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eopen\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/dev/pts/5\u0026#34;\u003c/span\u003e, O_RDWR \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e O_NOCTTY \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e O_NONBLOCK);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (fd \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e termios tio;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003etcgetattr\u003c/span\u003e(fd, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003etio) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e|=\u003c/span\u003e CLOCAL;  \u003cspan style=\"color:#75715e\"\u003e// 保证程序不占用串口\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e|=\u003c/span\u003e CREAD; \u003cspan style=\"color:#75715e\"\u003e// 使能读数据\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003eCRTSCTS;  \u003cspan style=\"color:#75715e\"\u003e// 不使用流控制\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003eCSIZE;  \u003cspan style=\"color:#75715e\"\u003e// 屏蔽其它标志位\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e|=\u003c/span\u003e CS8; \u003cspan style=\"color:#75715e\"\u003e// 8位数据位\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003ePARENB; \u003cspan style=\"color:#75715e\"\u003e// 无奇偶校验\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_iflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003eINPCK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_cflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003eCSTOPB; \u003cspan style=\"color:#75715e\"\u003e// 1位停止位\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_oflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003eOPOST;  \u003cspan style=\"color:#75715e\"\u003e// 原始数据输出\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\ttio.c_lflag \u003cspan style=\"color:#f92672\"\u003e\u0026amp;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003e(ICANON \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ECHO \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ECHOE \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ISIG);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ecfsetspeed\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003etio, B115200) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003etcsetattr\u003c/span\u003e(fd, TCSANOW, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003etio) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e; \u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003ei)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003ewrite\u003c/span\u003e(fd, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1234\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ok\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ((buf_len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eread\u003c/span\u003e(fd, buf, \u003cspan style=\"color:#ae81ff\"\u003e512\u003c/span\u003e)) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e buf_len; \u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003ei)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%c\u0026#34;\u003c/span\u003e, buf[i]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"posix"},{"content":"综述 由于perl是正则表达式的鼻祖，使用perl语法最为合适。 正则表达式一般用在“三剑客”(grep, sed, awk)和vim中。 要注意的是sed和vim都是行编辑模式。\n使用 比如批量重命名文件夹就会用到。\n1 for i in *; do echo \u0026#34;$i\u0026#34; |perl -pe \u0026#39;s/(\\[.+?\\]) *(.+)/\\2 \\1/\u0026#39;; done greedy 和 lazy 匹配 在* +后添加?\n转义字符 . ? + * [] {} /\n基本字符类 \\d 数字字符\t\\D 非数字字符\n\\w [a-zA-Z0-9_]\t\\W [^a-zA-Z0-9_]\n\\s 空白字符\t\\S\nPOSIX字符类 [:alnum:]\t[a-zA-Z0-9] [:alpha:]\t[a-zA-Z] [:xdigit:]\t[a-fA-F0-9] 边界匹配 \\b 单词边界\t\\B 环视（lookaround） 设置需要匹配不需要获取的部分。 因为lookahead比lookbehind实现更简单，所以lookbehind一般有字符数字的限制，lookahead则没有。\n向前查看（lookahead） 肯定式\t.+(?=:) 否定式 .+(?!:) 向后查看（lookbehind） 肯定式\t(?\u0026lt;=$)[0-9.]+ 否定式\t(?\u0026lt;!$)[0-9.]+ 嵌入式条件 (/()?\\d{3}(?(1))|-)\\d{3}-\\d{4}\n123-456-7890\n(123)456-7890\n常用正则表达式 邮政编码\n1 (((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5])) URL\n1 https?:\\/\\/[-\\w.]+(:\\d+)?(\\/([\\w\\/_.]*)?)? email\n1 (\\w+\\.)*\\w+@(\\w+\\.)+[A-Za-z]+ ","permalink":"https://kuang-r.github.io/posts/2021-01-13-%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/","summary":"\u003ch2 id=\"综述\"\u003e综述\u003c/h2\u003e\n\u003chr\u003e\n\u003cp\u003e由于perl是正则表达式的鼻祖，使用perl语法最为合适。\n正则表达式一般用在“三剑客”(grep, sed, awk)和vim中。\n要注意的是sed和vim都是行编辑模式。\u003c/p\u003e\n\u003ch2 id=\"使用\"\u003e使用\u003c/h2\u003e\n\u003cp\u003e比如批量重命名文件夹就会用到。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i in *; \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e echo \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$i\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e |perl -pe \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;s/(\\[.+?\\]) *(.+)/\\2 \\1/\u0026#39;\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"greedy-和-lazy-匹配\"\u003egreedy 和 lazy 匹配\u003c/h2\u003e\n\u003cp\u003e在* +后添加?\u003c/p\u003e\n\u003ch2 id=\"转义字符\"\u003e转义字符\u003c/h2\u003e\n\u003cp\u003e. ? + * [] {} /\u003c/p\u003e\n\u003ch2 id=\"基本字符类\"\u003e基本字符类\u003c/h2\u003e\n\u003cp\u003e\\d 数字字符\t\\D 非数字字符\u003c/p\u003e\n\u003cp\u003e\\w [a-zA-Z0-9_]\t\\W [^a-zA-Z0-9_]\u003c/p\u003e\n\u003cp\u003e\\s 空白字符\t\\S\u003c/p\u003e\n\u003ch2 id=\"posix字符类\"\u003ePOSIX字符类\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e[:alnum:]\t[a-zA-Z0-9]\u003c/li\u003e\n\u003cli\u003e[:alpha:]\t[a-zA-Z]\u003c/li\u003e\n\u003cli\u003e[:xdigit:]\t[a-fA-F0-9]\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"边界匹配\"\u003e边界匹配\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\\b 单词边界\t\\B\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"环视lookaround\"\u003e环视（lookaround）\u003c/h2\u003e\n\u003cp\u003e设置需要匹配不需要获取的部分。\n因为lookahead比lookbehind实现更简单，所以lookbehind一般有字符数字的限制，lookahead则没有。\u003c/p\u003e\n\u003ch3 id=\"向前查看lookahead\"\u003e向前查看（lookahead）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e肯定式\t.+(?=:)\u003c/li\u003e\n\u003cli\u003e否定式 .+(?!:)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"向后查看lookbehind\"\u003e向后查看（lookbehind）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e肯定式\t(?\u0026lt;=$)[0-9.]+\u003c/li\u003e\n\u003cli\u003e否定式\t(?\u0026lt;!$)[0-9.]+\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"嵌入式条件\"\u003e嵌入式条件\u003c/h2\u003e\n\u003cp\u003e(/()?\\d{3}(?(1))|-)\\d{3}-\\d{4}\u003c/p\u003e","title":"正则表达式"},{"content":"设置 1 2 # 自动保存http帐号密码 git config --global credential.helper store 版本控制 git difftool 1234 4321 file -y 比较不同提交差异 git commit --amend 追加提交 log 1 2 3 4 5 6 7 8 git log --since=2.weeks --until=2.days git log --since=\u0026#39;2020-05-01\u0026#39; --until=\u0026#39;2020-06-01\u0026#39; git log --author=kuang-R # 正则查找提交说明 git log --grep \u0026#34;update\u0026#34; # 查找添加或移除某个特定函数的提交 git log -Sfunction_name # --all-match tag 1 2 3 4 5 6 7 8 git tag -l \u0026#39;v1.8*\u0026#39; # annotated git tag -a v1.0 -m\u0026#34;my version 1.0\u0026#34; # lightweight git tag v1.0 git push --tags git tag -d v1.o git push origin :refs/tags/v1.0 远程仓库 git remote -v 查看远程仓库 git remote add name url 添加远程仓库 git push name branch -u 设为默认push仓库 .gitignore #开始的行会被忽略 以/开头禁止递归匹配（子目录） 以/结尾表示目录 !取反 ssh 1 2 ssh-keygen -t rsa -C \u0026#34;a1173522112@163.com\u0026#34; cat ~/.ssh/id_rsa.pub ","permalink":"https://kuang-r.github.io/posts/2021-01-13-git/","summary":"\u003ch2 id=\"设置\"\u003e设置\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 自动保存http帐号密码\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit config --global credential.helper store\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"版本控制\"\u003e版本控制\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003egit difftool 1234 4321 file -y\u003c/code\u003e 比较不同提交差异\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egit commit --amend\u003c/code\u003e 追加提交\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"log\"\u003elog\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e8\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit log --since\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e2.weeks --until\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e2.days\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit log --since\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;2020-05-01\u0026#39;\u003c/span\u003e --until\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;2020-06-01\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit log --author\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ekuang-R\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 正则查找提交说明\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit log --grep \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;update\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 查找添加或移除某个特定函数的提交\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit log -Sfunction_name\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# --all-match\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch3 id=\"tag\"\u003etag\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e6\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e7\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e8\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit tag -l \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;v1.8*\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# annotated\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit tag -a v1.0 -m\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;my version 1.0\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# lightweight\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit tag v1.0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit push --tags\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit tag -d v1.o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit push origin :refs/tags/v1.0\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"远程仓库\"\u003e远程仓库\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003egit remote -v\u003c/code\u003e 查看远程仓库\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egit remote add name url\u003c/code\u003e 添加远程仓库\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egit push name branch\u003c/code\u003e -u 设为默认push仓库\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"gitignore\"\u003e.gitignore\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e#开始的行会被忽略\u003c/li\u003e\n\u003cli\u003e以/开头禁止递归匹配（子目录）\u003c/li\u003e\n\u003cli\u003e以/结尾表示目录\u003c/li\u003e\n\u003cli\u003e!取反\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ssh\"\u003essh\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh-keygen -t rsa -C \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;a1173522112@163.com\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecat ~/.ssh/id_rsa.pub\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e","title":"自动保存http帐号密码"},{"content":"DEBUG 在freerots中断言有两种类型。官网描述\n关中断然后进入死循环，使用调试器定位出错位置 进入一个自定义的函数，输出文件名或者文件位置 1 2 3 4 5 6 /* Define configASSERT() to disable interrupts and sit in a loop. */ #define configASSERT( ( x ) ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } /* Define configASSERT() to call vAssertCalled() if the assertion fails. The assertion has failed if the value of the parameter passed into configASSERT() equals zero. */ #define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ) 值得注意的是，cubemx自动生成第一种类型的中断，而且是在USER code中生成的。 这意味着只需要将configASSERT定义为空就可以关掉debug设置，而且不会被新生成的代码覆盖。\n计算任务栈大小 -fstack-usage 这个参数会生成.su文件，文件中会记录每个函数使用栈大小。官网描述\n-Wstack-usage=128 如果函数栈超过128 bytes，编译器会给出一个警告。\nuxTaskGetStackHighWaterMark 这个函数会返回未用栈大小(word)。官网描述\nvApplicationStackOverflowHook 这个钩子函数在监测到有堆栈溢出时调用。官网描述\n计算任务栈 在freertos中绝对不可以使用递归 1 2 ./avstack.pl *.o cflow *.c 通过debug检查，防止爆栈 1 2 #define INCLUDE_uxTaskGetStackHighWaterMark 1 configASSERT(usTaskGetStackHighWaterMark(xTask) \u0026gt; 32); 通过钩子函数，防止爆栈 1 2 3 4 #define INCLUDE_uxTaskGetStackHighWaterMark 1 #define configCHECK_FOR_STACK_OVERFLOW 2 void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ); 总结 经过编译时检查和运行时检查，几乎能消除freertos所有的栈分配不当，提高代码质量。\n使用jlink RTT进行调试 jlink官方(UM08001)提供了一种基于内核的调试信息输出。 实现约占ROM 500 bytes，RAM几乎可以忽略。对比串口有如下优点\n连线少，debug和终端输出都是使用jlink 速度快，输出调试信息更多 RTT库能防止输出冲突 实现简单，只需要添加.c文件即可 多终端输出支持 添加库 RTT库在 SEEGER/JLINK/Samples/RTT文件夹中。\n1 2 3 4 SEGGER_RTT_Conf.h SEGGER_RTT.h SEGGER_RTT_printf.c SEGGER_RTT.c 将如上文件加入到项目内，编译通过即可使用。调试使用JLinkRTTViewer图形界面。\n1 2 3 4 5 6 7 #include \u0026#34;SEGGER_RTT.c\u0026#34; /× BufferIndex使用0即可，其他buffer需要注册 */ int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); /* 改变接下来的输出终端 */ void SEGGER_RTT_SetTerminal(char TerminalId); /× 不改变输出终端,输出信息 */ int SEGGER_RTT_TerminalOut(char TerminalID, const char *s); 已知bug JLinkRTTViewer: 如果输出终端号为0，可以识别\\n。其它终端号无法识别\\n。解决方案：使用JLinkRTTClent 在linux平台对utf8中文字符串识别出错。解决方案：即时调试使用JLinkRTTClient，保存记录使用JLinkRTTViewer ","permalink":"https://kuang-r.github.io/posts/2021-01-12-embed/","summary":"\u003ch3 id=\"debug\"\u003eDEBUG\u003c/h3\u003e\n\u003chr\u003e\n\u003cp\u003e在freerots中断言有两种类型。\u003ca href=\"https://www.freertos.org/a00110.html#configASSERT\"\u003e官网描述\u003c/a\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e关中断然后进入死循环，使用调试器定位出错位置\u003c/li\u003e\n\u003cli\u003e进入一个自定义的函数，输出文件名或者文件位置\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\n\u003ctable style=\"border-spacing:0;padding:0;margin:0;border:0;\"\u003e\u003ctr\u003e\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e1\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e2\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e3\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e4\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e5\n\u003c/span\u003e\u003cspan style=\"white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"\u003e6\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd style=\"vertical-align:top;padding:0;margin:0;border:0;;width:100%\"\u003e\n\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/* Define configASSERT() to disable interrupts and sit in a loop. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define configASSERT( ( x ) )     if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/* Define configASSERT() to call vAssertCalled() if the assertion fails.  The assertion\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003ehas failed if the value of the parameter passed into configASSERT() equals zero. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define configASSERT( ( x ) )     if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e值得注意的是，cubemx自动生成第一种类型的中断，而且是在USER code中生成的。\n这意味着只需要将configASSERT定义为空就可以关掉debug设置，而且不会被新生成的代码覆盖。\u003c/p\u003e","title":"embed"},{"content":"添加右键菜单 打开注册表HKEY_CLASSES_ROOT\\Directory\\Background\\shell 新建项msys2，默认值修改为msys2 新建字符串值，命名为icon，修改值为C:\\msys64\\msys2.icon 修改command的默认值为C:\\msys64\\msys2_shell.cmd -mingw64 -here ","permalink":"https://kuang-r.github.io/posts/2021-01-12-msys2/","summary":"\u003ch2 id=\"添加右键菜单\"\u003e添加右键菜单\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e打开注册表\u003ccode\u003eHKEY_CLASSES_ROOT\\Directory\\Background\\shell\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e新建项\u003ccode\u003emsys2\u003c/code\u003e，默认值修改为\u003ccode\u003emsys2\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e新建字符串值，命名为\u003ccode\u003eicon\u003c/code\u003e，修改值为\u003ccode\u003eC:\\msys64\\msys2.icon\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e修改command的默认值为\u003ccode\u003eC:\\msys64\\msys2_shell.cmd -mingw64 -here\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e","title":"msys2"},{"content":"将ADC的值编码成可播放的WAV 记录一些基础知识和原理\n声音 声音（sound)是由物体振动产生的声波，作为一种波，频率在20Hz~20kHz之间的声音是可以被人耳识别的。\n语音编码 原理 有一定电子基础的都知道传感器采集音频信号是模拟量，而我们实际传输过程中使用的是数字量。而这就涉及到模拟转数字的过程。 而模拟信号数字化必须经过三个过程，即抽样、量化和编码，以实现话音数字化的脉冲编码调制（PCM，Pulse Coding Modulation）技术。\n抽样(Sampling) 抽样是把模拟信号以其信号带宽2倍以上的频率提取样值，变为在时间轴上离散的抽样信号的过程。\n采样率 (sample) 每秒从连续信号中提取并组成离散信号的采样个数，用赫兹（Hz）来表示。\n量化（quantizing） 抽样信号虽然是时间轴上离散的信号，但仍然是模拟信号，其样值在一定的取值范围内，可有无限多个值。 显然，对无限个样值一一给出数字码组来对应是不可能的。为了实现以数字码表示样值，必须采用“四舍五入”的方法把样值分级“取整”，使一定取值范围内的样值由无限多个值变为有限个值。 这一过程称为量化。\n量化噪音 量化后的抽样信号与量化前的抽样信号相比较，当然有所失真，且不再是模拟信号。 这种量化失真在接收端还原模拟信号时表现为噪声，并称为量化噪声。 量化噪声的大小取决于把样值分级“取整”的方式，分的级数越多，即量化级差或间隔越小，量化噪声也越小。\n采样位数 指的是描述数字信号所使用的位数。 8位(8bit)代表2的8次方=256，16 位(16bit)则代表2的16次方=65536； 采样位数越高，精度越高。\n编码（Coding） 量化后的抽样信号就转化为按抽样时序排列的一串十进制数字码流，即十进制数字信号。 简单高效的数据系统是二进制码系统，因此，应将十进制数字代码变换成二进制编码。 根据十进制数字代码的总个数，可以确定所需二进制编码的位数，即字长(采样位数)。 这种把量化的抽样信号变换成给定字长的二进制码流的 过程称为编码。\n一些概念 采样频率 人对频率的识别范围是 20HZ - 20000HZ, 如果每秒钟能对声音做 20000 个采样, 回放时就足可以满足人耳的需求。\n8000hz 为电话采样。 22050 的采样频率是常用的。 44100已是CD音质, 超过48000的采样对人耳已经没有意义。 采样位数 每个采样数据记录的是振幅, 采样精度取决于储存空间（采样位数）的大小。\n1 字节(也就是8bit) 只能记录 256 个数, 也就是只能将振幅划分成 256 个等级。 2 字节(也就是16bit) 可以细到 65536 个数, 这已是 CD 标准了。 4 字节(也就是32bit) 能把振幅细分到 4294967296 个等级, 实在是没必要了。 如果是双声道(stereo), 采样就是双份的, 文件也差不多要大一倍。 比特率 码率，是指经过编码后的音频数据每秒钟需要用多少个比特来表示。\n有损和无损 对于我们最常说的“无损音频”来说，一般都是指传统CD格式中的16bit/44.1kHz采样率的文件格式。 而之所以称为无损压缩，也是因为其包含了20Hz-22.05kHz这个完全覆盖人耳可闻范围的频响频率而得名。\nPCM 音频编码 PCM信号未经过任何编码和压缩处理(无损压缩)。 与模拟信号比，它不易受传送系统的杂波及失真的影响。动态范围宽，可得到音质相当好的效果。编码上采用A律13折线编码。\nA律13折线 A律是PCM非均匀量化中的一种对数压扩形式。数字脉冲编码调制（PCM）是目前模拟信号数字化的基本方法，PCM包括采样、量化、编码三个步骤。 其中量化是对抽样值的取值离散，根据量化间隔的不同选取分为均匀量化和非均匀量化，非均匀量化可以有效地改善信号的量化信噪比。 语音信号的量化常采用ITU建议的两种对数形式的非均匀量化压缩特性：A律和μ律，A律编码主要用于30/32路一次群系统， A律PCM用于欧洲和中国。\n声道 声道可以分为单声道和立体声（双声道）。PCM的每个样本值包含在一个整数i中，i的长度为容纳指定样本长度所需的最小字节数。\n首先存储低有效字节，表示样本幅度的位放在i的高有效位上，剩下的位置为0，这样8位和16位的PCM波形样本的数据格式如下所示。 总结 通过ADC读取16位的一个字节数据，以小段模式单声道存储，最后加上wav头就可以播放。\nSTM32为12位ADC 读取到的数据需要经过转换。 设x为读到的数据。将其转换为16位数据。\n1 x/2^12*2^16（未化简） 例子代码的wav头（未验证） ","permalink":"https://kuang-r.github.io/posts/2021-01-12-%E5%A3%B0%E9%9F%B3%E9%87%87%E9%9B%86/","summary":"\u003ch1 id=\"将adc的值编码成可播放的wav\"\u003e将ADC的值编码成可播放的WAV\u003c/h1\u003e\n\u003cp\u003e记录一些基础知识和原理\u003c/p\u003e\n\u003ch2 id=\"声音\"\u003e声音\u003c/h2\u003e\n\u003cp\u003e声音（sound)是由物体振动产生的声波，作为一种波，频率在20Hz~20kHz之间的声音是可以被人耳识别的。\u003c/p\u003e\n\u003ch2 id=\"语音编码\"\u003e语音编码\u003c/h2\u003e\n\u003ch3 id=\"原理\"\u003e原理\u003c/h3\u003e\n\u003cp\u003e有一定电子基础的都知道传感器采集音频信号是模拟量，而我们实际传输过程中使用的是数字量。而这就涉及到模拟转数字的过程。\n而模拟信号数字化必须经过三个过程，即抽样、量化和编码，以实现话音数字化的脉冲编码调制（PCM，Pulse Coding Modulation）技术。\u003c/p\u003e\n\u003ch3 id=\"抽样sampling\"\u003e抽样(Sampling)\u003c/h3\u003e\n\u003cp\u003e抽样是把模拟信号以其信号带宽2倍以上的频率提取样值，变为在时间轴上离散的抽样信号的过程。\u003c/p\u003e\n\u003ch4 id=\"采样率-sample\"\u003e采样率 (sample)\u003c/h4\u003e\n\u003cp\u003e每秒从连续信号中提取并组成离散信号的采样个数，用赫兹（Hz）来表示。\u003c/p\u003e\n\u003ch3 id=\"量化quantizing\"\u003e量化（quantizing）\u003c/h3\u003e\n\u003cp\u003e抽样信号虽然是时间轴上离散的信号，但仍然是模拟信号，其样值在一定的取值范围内，可有无限多个值。\n显然，对无限个样值一一给出数字码组来对应是不可能的。为了实现以数字码表示样值，必须采用“四舍五入”的方法把样值分级“取整”，使一定取值范围内的样值由无限多个值变为有限个值。\n这一过程称为量化。\u003c/p\u003e\n\u003ch4 id=\"量化噪音\"\u003e量化噪音\u003c/h4\u003e\n\u003cp\u003e量化后的抽样信号与量化前的抽样信号相比较，当然有所失真，且不再是模拟信号。\n这种量化失真在接收端还原模拟信号时表现为噪声，并称为量化噪声。\n量化噪声的大小取决于把样值分级“取整”的方式，分的级数越多，即量化级差或间隔越小，量化噪声也越小。\u003c/p\u003e\n\u003ch4 id=\"采样位数\"\u003e采样位数\u003c/h4\u003e\n\u003cp\u003e指的是描述数字信号所使用的位数。\n8位(8bit)代表2的8次方=256，16 位(16bit)则代表2的16次方=65536； 采样位数越高，精度越高。\u003c/p\u003e\n\u003ch3 id=\"编码coding\"\u003e编码（Coding）\u003c/h3\u003e\n\u003cp\u003e量化后的抽样信号就转化为按抽样时序排列的一串十进制数字码流，即十进制数字信号。\n简单高效的数据系统是二进制码系统，因此，应将十进制数字代码变换成二进制编码。\n根据十进制数字代码的总个数，可以确定所需二进制编码的位数，即字长(采样位数)。\n这种把量化的抽样信号变换成给定字长的二进制码流的 过程称为编码。\u003c/p\u003e\n\u003ch2 id=\"一些概念\"\u003e一些概念\u003c/h2\u003e\n\u003ch3 id=\"采样频率\"\u003e采样频率\u003c/h3\u003e\n\u003cp\u003e人对频率的识别范围是 20HZ - 20000HZ, 如果每秒钟能对声音做 20000 个采样, 回放时就足可以满足人耳的需求。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e8000hz 为电话采样。\u003c/li\u003e\n\u003cli\u003e22050 的采样频率是常用的。\u003c/li\u003e\n\u003cli\u003e44100已是CD音质, 超过48000的采样对人耳已经没有意义。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"采样位数-1\"\u003e采样位数\u003c/h3\u003e\n\u003cp\u003e每个采样数据记录的是振幅, 采样精度取决于储存空间（采样位数）的大小。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e1 字节(也就是8bit) 只能记录 256 个数, 也就是只能将振幅划分成 256 个等级。\u003c/li\u003e\n\u003cli\u003e2 字节(也就是16bit) 可以细到 65536 个数, 这已是 CD 标准了。\u003c/li\u003e\n\u003cli\u003e4 字节(也就是32bit) 能把振幅细分到 4294967296 个等级, 实在是没必要了。\n如果是双声道(stereo), 采样就是双份的, 文件也差不多要大一倍。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"比特率\"\u003e比特率\u003c/h3\u003e\n\u003cp\u003e码率，是指经过编码后的音频数据每秒钟需要用多少个比特来表示。\u003c/p\u003e","title":"将ADC的值编码成可播放的WAV"},{"content":"我是阮华锋，这是我的个人博客，记录技术学习与生活随想。\n联系邮箱：a1173522112@163.com GitHub：kuang-R\n","permalink":"https://kuang-r.github.io/about/","summary":"\u003cp\u003e我是阮华锋，这是我的个人博客，记录技术学习与生活随想。\u003c/p\u003e\n\u003cp\u003e联系邮箱：a1173522112@163.com\nGitHub：\u003ca href=\"https://github.com/kuang-R\"\u003ekuang-R\u003c/a\u003e\u003c/p\u003e","title":"关于"}]