绿色线程: 原理与实现

绿色线程: 原理与实现

引言: 绿色线程(Green threads)即在用户态实现的线程, 是相对于操作系统线程(Native threads)提出的概念. 绿色线程完全由编程语言运行时环境或VM进行调度管理, 实现的是合作式的”伪”并发. 在Java 1.1中, 绿色线程是JVM中唯一的线程模型, 当时的人们普遍认为绿色线程避免了频繁的内核态-用户态切换, 在一些特定场景下可以达到更好的性能. 然而, 随着操作系统和编程语言的发展, 绿色线程由于种种原因逐渐被抛弃. 直到近年来, Go语言中goroutine的广泛使用, 用户态线程管理这一技术才重新吸引了人们的目光.

Why Threads in User Space

在分析实现原理前, 我们首先来思考一下, 既然操作系统底层已经提供了的完整的线程支持, 为什么还需要用户态线程? 前面我们提到了Go近年来迅猛发展, 而这里的答案也正与goroutine擅长处理的场景有关: 高并发.

对于并发场景, 常见的处理方式有以下几种:

  1. 多进程, 例如Apach的Prefork模式
  2. 多线程+锁, Java开发中最常用的模式
  3. 异步回调+事件驱动, 例如node.js
  4. 用户态线程/协程/纤程/绿色线程, 例如goroutine

其中, 进程消耗系统资源相对较大, 因此多进程并不适合高并发场景; 多线程避免了进程的堆, 地址空间等资源的重复分配, 相比于多进程, 大大降低了多任务并行调度的开销; 回调+事件轮询的处理模型采用了不同的思路, 通过非阻塞的方式保持CPU的持续运转; 用户态线程则是将线程的调度逻辑从内核态转移到了用户态, 相较于多线程进一步地减少了调度的开销, 实现了更细粒度的控制.

用户态线程的优势主要在于:

  1. 调度代价小: 用户态线程避免了特权级的转换, 而且仅使用部分寄存器即可完成上下文切换(见下文实现).
  2. 内存占用少: 内核线程的栈空间通常为1-2MB, 用户态线程(如goroutine)栈空间最小可以到2KB, 一个golang程序可以轻松支持10万级别的goroutine运行, 作为对比, 1000个系统线程已经需要至少1-2GB的内存了.
  3. 解决回调地狱: 用户态线程可以简化异步回调的代码, 提升开发人员编码的简洁性和可读性.

实现原理

线程结构体

为了实现绿色线程, 我们首先需要确定描述一个线程需要哪些信息. 根据线程的定义不难发现, 描述线程的结构体应该包括:

  • 线程ID
  • 运行状态
  • PC
  • 通用寄存器

x86_64架构下, 上述线程描述可以用以下代码来表示:

struct Thread {
    _id: usize,
    stack: Vec<u8>,
    ctx: ThreadContext,
    state: State,
}

struct ThreadContext {
    rsp: u64,
    r15: u64,
    r14: u64,
    r13: u64,
    r12: u64,
    rbx: u64,
    rbp: u64,
}

enum State {
    Available,
    Running,
    Ready,
}

继续阅读“绿色线程: 原理与实现”

Intel SGX: 基本概念

SGX是Intel实现的可信执行环境,主要面向服务器和桌面端,提供了内存加密(Memory Encryption)、访问控制(Access Control)、远程认证(Remote Attestation)、本地密封(Sealing)等功能。

0x00 Overview

关于应用程序代码与可信执行环境的基本关系:

  1. 每个application分为两部分:安全(可信)部分和不安全(不可信)的部分
  2. application启动后,会在受保护的可信内存中加载一块飞地(enclave)
  3. application通过把机密数据、代码放到enclave里来保证安全性
  4. enclave为application提供调用接口,当application调用enclave内的函数时,其内部的任何内存仅enclave自身可见
  5. enclave内存即使ring 0的攻击者也看不到,因为是CPU层面的保护。实际上在SGX的安全模型里OS、BIOS等等都可以被认为是不可信的

关于可信执行环境与用户进程的关系:

  1. application 本身包括了自身的代码、数据和enclave
  2. enclave里面也有其自身的代码、数据
  3. SGX保证enclave里面的代码和数据的integrity和confidentiality
  4. enclave的entry points在编译期就确定了
  5. enclave可以访问它所在的application里的内存,但是反过来不行
  6. 支持多线程


继续阅读“Intel SGX: 基本概念”

[娱乐][代理][CF] 使用cloudflare worker反向代理codeforces,支持登录和提交代码评测

作为一个退役的ACM选 (蒟)手(蒻),偶尔也会回codeforces上做做题娱乐娱乐。。

但是codeforces作为一个外国网站,在国内访问的话速度十分感人,你懂的。

虽然绝大多数 业内人士 都有不可描述的方法让自己访问到国外的网站,但是还是有一些刚接触比赛的同学需要一个比较快的访问途径。当然国内之前也有一些dalao自制的codeforces镜像,例如 https://codeforc.es/ 等。

我这里提供一种免费自行搭建codeforces反向代理的方法,借用了cloudflare免费提供的serveless服务:workers。关于workers的简单介绍可以参见官方的blog:

Cloudflare Workers的名称来自Web Workers,更具体地说是Service Workers,一个用于在web浏览器后台运行并拦截HTTP请求的脚本的W3C标准API。Cloudflare Workers是针对相同的标准API编写的,但是是在Cloudflare的服务器上运行,而不是在浏览器中运行。
以下是您可以使用的工具:
– 使用最新的标准语言功能执行任意JavaScript代码。
– 拦截和修改HTTP请求和响应URL,状态,标头和正文内容。
– 直接从您的Worker响应请求,或将其转发到其他地方。
– 将HTTP请求发送到第三方服务器。
– 以串行或并行方式发送多个请求,并使用响应组成对原始请求的最终响应。
– 在响应已经返回到客户端之后发送异步请求(例如,用于记录或分析)。
– 控制其他Cloudflare功能,例如缓存行为。
– 显然我们要达到反向代理的目的只需要处理两件事:
– 处理客户端的请求,修改参数之后发送给真正的服务端(codeforces.com)
– 处理codeforces.com返回的响应,修改参数后发给客户端
继续阅读“[娱乐][代理][CF] 使用cloudflare worker反向代理codeforces,支持登录和提交代码评测”

图片转latex/word代码在线工具,mathpix的在线替代,完全免费,避免重复劳动

使用示例

使用方法

用截图工具(QQ 微信等的截图或者Windows自带的截图)截图或将图片复制到剪切板后在本页面按Ctrl+V粘贴即可在文本框内获取latex代码。注意Word的代码复制出来之后再Word里粘贴要用 右键-> 粘贴 -> 仅粘贴文本 的方式

地址: https://mathcode.herokuapp.com/ 建议加入书签。由于是部署在heroku美国上(买不起服务器和域名)所以国内直连会比较卡。

新地址:https://mathf.itewqq.cn/ 建议加入书签。为了方便国内连接我迁移到了自己的国内学生机上。网页打开速度变快了,但是腾讯云的学生机总带宽只有1M所以人多的时候用可能还是会卡(贫穷.jpg)

继续阅读“图片转latex/word代码在线工具,mathpix的在线替代,完全免费,避免重复劳动”

BUUOJ Web #1 [HCTF 2018]WarmUp [强网杯 2019] 随便注 [SUCTF 2019]EasySQL [RoarCTF 2019]Easy Calc

0x01 [HCTF 2018] WarmUp [PHP][代码审计]

题目链接

简单题。打开网页后一张滑稽,按F12寻找信息,发现代码注释里有一行
“`“`,在url后加上/source.php刷线页面,得到一段PHP代码。

<?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?>

看这个判断语句

if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    )

说明是在请求中包含有文件,以及文件是一个string,这两个都好说,看第三个是进入checkFile函数。

看代码逻辑的话,有三种情况会返回true
继续阅读“BUUOJ Web #1 [HCTF 2018]WarmUp [强网杯 2019] 随便注 [SUCTF 2019]EasySQL [RoarCTF 2019]Easy Calc”

Docker搭建Nextcloud私有云++Aria2下载器

最近需要从国外某网站下载一个大的数据集,不知道为什么总是断流,而且不能续传,非常烦人。后来想了想,可以在国外的vps上搭一个私人云盘,然后先把数据下到vps上,再下到我的本机上,曲线救国。然后搜索了下发现Nextcloud+Aria2是比较好的一个选择,而且有docker,十分的方便,就简单部署了一下。

其中docker-compose.yml如下,其中的端口映射因为我这台vps上已经有了一个网站了,占用了80和443端口,所以修改了一下外部端口。

version: '3.5'

services:
  nextcloud:
    image: nextcloud:latest
    volumes:
      - ./data/nextcloud:/var/www/html:rw # moutn nextcloud files folder
      - ./data:/data:rw # mount your personal data folder
    restart: always
  aria2:
    image: wahyd4/aria2-ui:nextcloud
    ports:
      - "2480:80"
      - "2443:443"
    volumes:
      - ./data:/data # mount your personal data folder
    environment:
      - DOMAIN=:80
    links:
      - nextcloud:file-manager
    restart: always

写好之后我们直接docker-compose up -d启动,访问http://ip:2480即可登录nextcloud,http://ip:2480/ui/ 则是Aria2NG的管理页面。
继续阅读“Docker搭建Nextcloud私有云++Aria2下载器”

2019 kali 笔记本电脑 双系统 双显卡 配置nvidia显卡支持外接hdmi显示器

。。。绝大多数人都会照着官方的教程做,但是这个操作是针对只有一张nvidia显卡的台式机来说的,而不是笔记本的双显卡。。。。按照这个教程,装完之后是可以用这个gpu做运算的,但是不能用来做显示。。。插上外接显示器没有任何反应,用xrandr根本检测不到有外界显示器存在。

出现这个问题的原因是官方的配置里缺少了一步配置显示的操作。。。如果只有一张卡的话装系统的时候显示设置就配置好了,双显卡的话默认的显示用的是核显,独显根本没管,所以我们要手动操作一下。

注意:在参考本配置之前请务必先按照官网Doc走一遍,确保gpu驱动已经装好,可以进行运算测试之后再进行。

我的kali版本

Linux 5.3.0-kali2-amd64 #1 SMP Debian 5.3.9-3kali1 (2019-11-20) x86_64 GNU/Linux
  1. 首先安装kernel headers,不然驱动编译可能会出问题
apt install linux-headers-$(uname -r)

继续阅读“2019 kali 笔记本电脑 双系统 双显卡 配置nvidia显卡支持外接hdmi显示器”

UEFI双系统下手动删除Ubuntu引导

准备换电脑,把手上这台给我爸玩了,然后想着把Ubuntu删除掉只留个windows。删除双系统里的ubuntu,肯定要先解决引导的问题,然后再在磁盘管理里删除该系统所在卷了,但是操作过程中发现我的ubuntu引导的删除有问题,记录一下操作方法防止自己以后再乱搞。

首先确认本机是UFEI引导的,以管理员身份打开cmd然后输入 bcdedit /enum {current},如果显示结果如下,path的值为winload.efi则为uefi引导。

此时网络上流行的通用做法是在win10下用EasyUEFI软件中的管理EFI启动项功能来删除ubuntu引导,但是我自己的电脑用这个方法在软件里删除之后重启发现引导还在那儿没动,想了下可能是因为之前某次沙雕的 rm -rf /* 把引导搞坏了。。。当时只是修复了下Windows的引导,ubuntu直接重装了,可能留下了某些隐患现在暴露出来了emmmmm

那借助软件删除不了的话只能自己暴力手动操作了,首先可以想想,这个EasyUFEI软件本身也只是删除了引导文件而已,只要我自己手动的删除这些文件也可以达到相同的效果。利用这个软件的时候可以看到,在ubuntu选项的旁边会给出来 文件路径 这一行,长得类似于 继续阅读“UEFI双系统下手动删除Ubuntu引导”

配置vscode连接远程服务器

今年5月左右微软给vscode加了新操作,有了官方的远程连接的插件,不过好像现在只在insider版本里提供。要安装的话直接在插件里搜索Remote,安装Remote Development这一套就行了。

服务器上操作

这里配置一下使用ssh key登录,相对于输密码比较安全(其实是我懒得每次都敲密码)。首先在服务器上生成一对公私钥

root@itemqqSS:~# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:RWDHVoBeg7jvzTdC/nPPTwemzGl0vogQwUzmooas root@itemqqSS
The key's randomart image is:
+---[RSA 2048]----+
|       o=*+o.    |
|    . o====      |
|   . o+o +..     |
|  . . .o..       |
|   .   .S   . +  |
|  .    o. .+ * . |
| .     .o=. * . o|
|E       .o=++..+.|
|          .+o+..=|
+----[SHA256]-----+

这里最好不要再用passphrase了。。直接回车就行。。主要是图省事,加了之后vscode的自动连接似乎不是很方便。
继续阅读“配置vscode连接远程服务器”