操作系统相关知识总结

用户态与内核态

CPU分不同的指令级别

linux内核跑在ring 0 级,用户程序跑在ring 3,对于系统的关键访问,需要经过kernel同意,保证系统健壮性

内核执行的操作->200多个系统调用sendfile read write pthread fork

进程  线程  纤程

面试高频题:进程和线程有什么区别?

进程就是一个程序运行起来的状态,线程是一个进程中的不同的执行路径

专业答案:进程是OS分配资源的基本单位,线程是执行调度的基本单位。

分配资源最重要的是:独立的内存空间,线程调度执行(线程共享进程的内存空间,没有自己独立的内存空间)

线程在Linux中的实现:

就是一个普通进程,只不过和其他进程共享资源(内存空间 全局数据等。。。)

Linux中起一个进程,就是调用fork()函数。例如进程1,在进程1中想起一个线程,其实也是调用fork()起一个进程,只不过起的这个进程和进程1是共享内存的。

其他系统都有各自的所谓LWP的实现Light Weight Process---轻量级进程

高层面理解:一个进程中的不同的执行路线

fiber---纤程/协程(线程中的线程)

纤程:用户态的线程,线程中的线程,切换和调度不需要经过OS

优势:

1:占有资源很少,OS起一个线程占用1M,纤程占用4K

2:切换比较简单

3:启动很多个10W+

目前支持内置纤程的语言:Kotlin Scala Go Python(lib)...  java目前在jdk14是不支持的,但是通过类库是可以实现的(open jdk:loom)

java中对于纤程的支持:没有内置,盼望内置

利用Quaser库(不成熟)

依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zy.jvm</groupId>
    <artifactId>jvm</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/co.paralleluniverse/quasar-core -->
        <dependency>
            <groupId>co.paralleluniverse</groupId>
            <artifactId>quasar-core</artifactId>
            <version>0.7.5</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

线程实现:

package com.mashibing.jvm.os;
public class HelloFiber {
    public static void main(String[] args) throws  Exception {
        long start = System.currentTimeMillis();
        Runnable r = new Runnable() {
            @Override
            public void run() {
                calc();
            }
        };
        int size = 100000;
        Thread[] threads = new Thread[size];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(r);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].join();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    static void calc() {
        int result = 0;
        for (int m = 0; m < 10000; m++) {
            for (int i = 0; i < 200; i++) result += i;

        }
    }
}

纤程是实现:

package com.mashibing.jvm.os;

import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.SuspendableRunnable;

public class HelloFiber2 {
    public static void main(String[] args) throws  Exception {
        long start = System.currentTimeMillis();


        int size = 100000;

        Fiber<Void>[] fibers = new Fiber[size];

        for (int i = 0; i < fibers.length; i++) {
            fibers[i] = new Fiber<Void>(new SuspendableRunnable() {
                public void run() throws SuspendExecution, InterruptedException {
                    calc();
                }
            });
        }

        for (int i = 0; i < fibers.length; i++) {
            fibers[i].start();
        }

        for (int i = 0; i < fibers.length; i++) {
            fibers[i].join();
        }

        long end = System.currentTimeMillis();
        System.out.println(end - start);


    }

    static void calc() {
        int result = 0;
        for (int m = 0; m < 10000; m++) {
            for (int i = 0; i < 200; i++) result += i;

        }
    }
}

作业:目前是10000个Fiber -> 1个JVM线程,想办法提高效率,10000Fiber -> 10份 -> 10Threads

纤程的应用场景

纤程 vs 线程池:很短的计算任务,不需要和内核打交道,并发量高!

进程

linux中也称为task,是系统分配资源的基本单位

资源:独立的地址空间 内核数据结构  (进程描述符...) 全局变量  数据段...

进程描述符:PBC(Process Control Block)

进程创建和启动

系统函数fork() exec()

从A中fork B的话,A称为B的父进程

什么是僵尸进程

ps -ef | grep defuct

父进程产生子进程后,会维护子进程的一个PCB结构,子进程退出,由父进程释放,如果父进程没有释放,那么子进程成为一个僵尸进程(大多是情况下僵尸进程是没有什么影响的,因为只是维护一个PCB描述符,子进程的资源都会释放,影响不是很大,但是如果太多僵尸进程,肯定还是有影响的)

zombie.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
​
int main() {
        pid_t pid = fork();
​
        if (0 == pid) {
                printf("child id is %d\n", getpid());
                printf("parent id is %d\n", getppid());
        } else {
                while(1) {}
        }
}

什么是孤儿进程

子进程结束之前,父进程已经退出  孤儿进程会成为init进程的孩子,由1号进程维护

orphan.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
​
int main() {
        pid_t pid = fork();
​
        if (0 == pid) {
                printf("child ppid is %d\n", getppid());
                sleep(10);
                printf("parent ppid is %d\n", getppid());
        } else {
                printf("parent id is %d\n", getpid());
                sleep(5);
                exit(0);
        }
}
​

进程调度

内核进程调度器决定:该哪一个进程运行?何时开始?运行多长时间?   

 

进程调度的算法:

非抢占式(cooperative multitasking)除非进程主动让出cpu(yielding),否则将一直运行

抢占式(preemptive multitasking)由进程调度器强制开始或暂停(抢占)某一进程的执行

进程调度

2.6采用CFS调度策略:Completely Fair Scheduler

按优先级分配时间片的比例,记录每个进程的执行时间,如果有一个进程执行时间不到它应该分配的比例,优先执行。

进程调度基本概念

进程类型:

IO密集型 大部分时间用于等待IO

CPU密集型 大部分时间用于闷头计算

进程优先级

实时进程 > 普通进程

实时进程中又分为100个优先级(0 - 100)

普通进程nice值(-20 ~ 19)

Linux默认的调度策略

对于实时进程(急诊):使用SCHED_FIFO(先进先出)和SCHED_RR(轮询)两种

对于普通进程:使用CFS

其中等级最高的是FIFO,这种进程除非自己让出CPU否则Linux会一直执行它

除非更高级的FIFO和RR抢占它

RR只是这种这种进程中是同级别FIFO中的平均分配 ---- 比如FIFO中有两个都是90优先级的进程,这时候按照RR执行。

只有实时进程主动让出,或者执行完毕后,普通继承才有机会运行。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值