0714学习笔记

朝花夕拾

先回答一下昨天的疑问:

  1. 什么是用户级线程和内核级线程?

    以下是chatgpt编写的ULT和KLT的示例c代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <ucontext.h>
    
    #define STACK_SIZE 1024*64
    
    ucontext_t ctx_main, ctx_thread1, ctx_thread2;
    
    void thread_func1() {
        for (int i = 0; i < 5; i++) {
            printf("Thread 1: %d\n", i);
            swapcontext(&ctx_thread1, &ctx_thread2);  // 切换到线程2
        }
        printf("Thread 1 finished\n");
        setcontext(&ctx_main);  // 结束返回主程序
    }
    
    void thread_func2() {
        for (int i = 0; i < 5; i++) {
            printf("Thread 2: %d\n", i);
            swapcontext(&ctx_thread2, &ctx_thread1);  // 切换到线程1
        }
        printf("Thread 2 finished\n");
        setcontext(&ctx_main);
    }
    
    int main() {
        char stack1[STACK_SIZE];
        char stack2[STACK_SIZE];
    
        // 初始化线程1上下文
        getcontext(&ctx_thread1);
        ctx_thread1.uc_stack.ss_sp = stack1;
        ctx_thread1.uc_stack.ss_size = sizeof(stack1);
        ctx_thread1.uc_link = &ctx_main;  // 线程结束返回主上下文
        makecontext(&ctx_thread1, thread_func1, 0);
    
        // 初始化线程2上下文
        getcontext(&ctx_thread2);
        ctx_thread2.uc_stack.ss_sp = stack2;
        ctx_thread2.uc_stack.ss_size = sizeof(stack2);
        ctx_thread2.uc_link = &ctx_main;
        makecontext(&ctx_thread2, thread_func2, 0);
    
        // 从主线程切换到线程1开始执行
        swapcontext(&ctx_main, &ctx_thread1);
    
        printf("Main finished\n");
        return 0;
    }
    
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    void* func1(void* arg) {
        for (int i = 0; i < 5; i++) {
            printf("pthread func1: %d\n", i);
            sleep(1);  // 模拟阻塞
        }
        return NULL;
    }
    
    void* func2(void* arg) {
        for (int i = 0; i < 5; i++) {
            printf("pthread func2: %d\n", i);
            sleep(1);
        }
        return NULL;
    }
    
    int main() {
        pthread_t t1, t2;
    
        pthread_create(&t1, NULL, func1, NULL);
        pthread_create(&t2, NULL, func2, NULL);
    
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
    
        printf("All pthreads finished\n");
        return 0;
    

    可以看出,实际上ULT是在模拟KLT的实现思想,其调度和上下文切换都是用户程序自己显式实现的,但对于系统来说这仅仅是一个进程而已。那看来多对多的模型就是先申请多个内核,再在每个内核内使用ULT编程。

  2. PCB都包含什么?

    类别 信息
    进程标识信息 PID(进程ID)、PPID(父进程ID)、UID(用户ID)、GID(组ID)
    进程状态 就绪、运行、等待、终止等
    寄存器现场 程序计数器(PC)、栈指针(SP)、通用寄存器等
    内存管理信息 代码段、数据段、堆、栈、页表指针
    调度信息 优先级、时间片、调度队列信息、调度策略(如 SCHED_NORMAL)
    文件系统信息 文件描述符表、当前工作目录、打开文件列表
    会计信息 CPU时间、用户时间、系统时间、起始时间
    信号处理信息 信号屏蔽字、信号处理函数
    其他资源信息 IPC 资源(消息队列、共享内存)、网络信息等

    等配一个linux docker 用命令行敲一下。

  3. 访管中断和自陷指令有和关系?

自陷指令 访管中断
CPU 支持的汇编指令,用于产生陷入 操作系统级的概念,指的是进程通过自陷调用系统服务
比如:int 0x80(x86)、svc(ARM)、ecall(RISC-V) 访管中断就是自陷指令触发的中断,用来“访问管态(内核态)”服务
本质是硬件机制 本质是软件设计

“访管中断”是

“用自陷指令引发的,主动请求操作系统服务的中断”。

数学

三角函数大家族

一些恒等式

$$ \sin^2{\theta} + \cos^2{\theta} = 1 $$

$$ 1 + \tan^2{\theta} = \sec^2{\theta} $$

$$ 1 + \cot^2{\theta} = \csc^2{\theta} $$

$$ \sin(\arcsin{x}) = x(x\in[-1,1]) $$

$$ \sin(\arccos{x}) = \sqrt{1-x^2}(x\in[-1,1]) $$

$$ \cos(\arccos{x}) = x(x\in[-1,1]) $$

$$ \cos(\arcsin{x}) = \sqrt{1-x^2}(x\in[-1,1]) $$

双曲正弦/余弦函数

双曲正弦函数

$$ \sinh{x} = \frac{e^x-e^{-x}}{2} $$

反双曲正弦函数

$$ \text{arcsinh}\ {x} = \ln(x+\sqrt{1+x^2}) $$

$$ \text{arcsinh}'\ {x} = \frac{1}{\sqrt{1+x^2}} $$

双曲余弦函数

$$ \cosh{x} = \frac{e^x+e^{-x}}{2} $$

反双曲余弦函数

$$ \text{arccosh}\ {x} = \ln(x+\sqrt{x^2-1}),\ x\geq 1\\ $$$$ \text{arccosh}'\ {x} = \frac{1}{\sqrt{x^2-1}},\ x>1 $$

双曲正切函数

$$ \tanh{x} = \frac{\sinh{x}}{\cosh{x}}=\frac{e^x-e^{-x}}{e^x+e^{-x}} $$

反双曲正切函数

$$ \text{arctanh}\ {x} = \frac{1}{2}\ln(\frac{1+x}{1-x}),\ x\in(-1,1) $$$$ \text{arctanh}'\ {x} = \frac{1}{1-x^2} $$