问:进程和线程有什么区别? 进程最重要的资源,是它被分配的自己独立的内存空间。 程序开始执行之后,首先有一个 操作系统的线程是怎么实现的? JVM(HotSpot)和操作系统的线程是一一对应的:JVM空间的一个线程,对应操作系统中的一个线程,这是重量级线程。 操作系统可以开启的线程是有限的(1万个已经很卡了),而纤程是用户空间的,不需要与内核打交道,轻量级,切换速度快,可以启动几万个,甚至几十万个都没有问题。 纤程 纤程的优势 2020目前支持内置纤程的语言 如果大规模应用在生产,还是有一些小bug存在的。 pom.xml HelloFiber.java 线程版 HelloFiber2.java 纤程版 可再优化: 这样既充分利用了操作系统在内核级别对于线程的调度,又充分利用了JVM在用户空间的对于纤程的调度。 纤程应用在很短的计算任务,不需要和内核打交道,并发量高的时候,适合使用纤程。 内核线程是内核独用的线程,用来进行一些后台操作,比如垃圾清理等。 在Linux中,fork 底层调用的是 clone,是从当前进程 clone 出一个新的进程来。 在大多数情况下,少量僵尸进程的存在,对操作系统没有太大影响,它基本不再占用任何资源了,它在内存中唯一占用的资源就是PCB了。 孤儿进程产生的原因:子进程还活着,父进程挂了 孤儿进程和孤儿线程没有太大区别,因为在Linux中,进程和线程没有太大区别。 孤儿进程c示例: 运行结果 Linux中特别灵活,有各种各样的调度方案,可以写内核去自定义。 (目前)Linux 2.6 内核版本采用  CFS调度策略:按优先级分配时间片的比例,记录每个进程的执行时间,如果有一个进程执行时间不到他应该分配的比例(比如给了你50%,你只用了10%),就优先执行这个进程作为补偿。 Linux 默认调度策略: 1、实时进程:先执行 2、普通进程: CFS完全公平策略 外设的输入随时都有可能到达,cpu如何及时的知道并进行处理呢? cpu提供中断机制来满足这种需要,当cpu的内部有需要处理的事情发生时,将产生中断信息,引发中断过程,这种中断信息来自cpu内部,还有一种中断信息,来自于cpu外部,当cpu外部有需要处理的事情发生的时候,比如说,外设的输入到达,相关芯片将向cpu发出相应的中断信息。cpu在执行完当前指令后,可以检测到发送过来的中断信息,引发中断过程,处理外设的输入。 键盘、网卡、打印机、时钟计时器的中断,都属于硬中断。 软件产生的中断,做系统调用时,需要惊动内核。 阿里面试题:解释80中断的执行过程 搭建CentOS汇编环境 编译: 一个程序的执行过程,要么处于用户态,要么处于内核态
面试高频问题
 答:进程是一个程序运行起来的状态(运行态),线程是一个进程中不同的执行路径(线程只是其中一个)。
 更为专业的回答:进程是操作系统用来分配资源的基本单位,线程是操作系统用来执行调度的基本单位。进程、线程、纤程
1、进程

 双击QQ.exe,操作系统通过IO把它从磁盘取出来,放进内存中,形成一个进程。
 再双击QQ.exe,又开启一个进程…(同一个可以多次启动,开启多个进程)main主线程。之后可能会有其他的线程,线程调度执行。
 
 
 线程和进程的区别:
 (标准回答)线程共享进程的内存空间,没有自己独立的内存空间。
 不同的操作系统对于线程的实现是不同的。
 可以读一下《Linux内核设计与实现》
 
 在Linux中,进程就是一个fork,会从现有的进程里面开启一个新的子进程。
 在Linux里面,进程和线程没有太大的区别,线程就是一个普通的进程,只不过和其他进程共享资源(内存空间、全局数据等…)
 在其他操作系统中(比如Windows,Solaris),有各自LWP的实现,线程是轻量级进程。
 
协程(纤程)
 纤程可以被理解为:线程里的线程,在JVM层级用软件进行内部的线程协调。
 纤程是被JVM管理,运行在用户态,操作和调度不经过操作系统内核。
 关于纤程的实现:纤程可以分配自己独立的纤程栈,相当于自己实现了一个小小的操作系统级别的调度程序。
 1、占有资源很少。操作系统启动一个线程占用1M的内存空间,而启动一个纤程只需要4K空间
 2、由于轻量级,切换简单
 3、由于轻量级,可以启动几十万个纤程都没有问题。
 Kotlin Scala Go Python(+lib)
 Java通过类库可以支持:OpenJDK的loom项目正在做纤程的尝试。目前 JDK 14 还没有支持纤程,期待 JDK 15 吧…利用Quaser库(不成熟)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="https://maven.apache.org/POM/4.0.0"          xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>      <groupId>mashibing.com</groupId> <artifactId>HelloFiber</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.8.0</version> </dependency> </dependencies>  </project> 
 耗时7s
 
import co.paralleluniverse.fibers.Fiber; import co.paralleluniverse.fibers.SuspendExecution; import co.paralleluniverse.strands.SuspendableRunnable;  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 = 10000;          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; } } } 
 耗时3simport 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 = 10000;          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; } } } 
纤程的应用场景
 如果是读文件之类的任务,用线程比较好。内核线程(了解)
 
进程创建和启动
 
僵尸进程、孤儿进程
1、僵尸进程
 僵尸进程的产生原因,有可能父进程是一个daemon进程,C程序开发人员在父进程没有释放子进程,这时会出现僵尸进程。
 可以使用内核中的wait函数,释放僵尸进程
 
 僵尸进程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(); // 从 A 进程 fork 出来一个子进程 B      if (0 == pid) { // 这段是在 fork 的子进程执行的 B printf("child id is %dn", getpid()); printf("parent id is %dn", getppid()); // main 进程的 id } else { // 这段是执行的进程 A while(1) {} } } 
2、孤儿进程
 孤儿进程的影响:影响不大。#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 %dn", getppid()); // 打印爹的 id 号 sleep(10); // 子进程睡 10 秒,此过程中父进程已经主动退出了 printf("parent ppid is %dn", getppid()); // 换了个爹 } else { // 这里是父进程 printf("parent id is %dn", getpid()); // 打印自己的 id 号 sleep(5); // 睡 5 秒 exit(0); // 父进程主动退出 } } 
 
 进程号1457的进程,它的父亲进程号是1
 
进程调度
 
 
 
进程调度
CFS 调度策略:Completely Fair Scheduler 完全公平
 
 进程调度基本概念
 

中断
 
 如何用硬件的电信号控制软件的输出的?
 1、键盘按下后,CPU去查是哪种类型的中断
 2、如果这个中断在中断向量表中,CPU到内存中的一个固定位置找到对应的中断处理程序,进行处理

硬中断
软中断
 比如想要和硬盘打交道,需要调用内核,让内核去做硬盘的访问,这是软中断。
 软件给内核一个 0x80中断 信号,然后去调用200多个函数中的一个。
 int 0x80 是C语言的函数,现在 intel 已经直接移植到了硬件层面,sysenter原语是汇编语言实现的。
 bx cx dx si di存储着内核函数的5个参数
 比如,InputStream中的read()方法:
 
从汇编角度理解80软中断
 yum install nasm;hello.asm ;write(int fd, const void *buffer, size_t nbytes) 调用了内核空间的write函数 ;fd 文件描述符 file descriptor - linux下一切皆文件,网络、硬盘、内存、打印机、屏幕都可以对应到各自的文件描述符  section data     msg db "Hello", 0xA ;定义一个字符串hello   0xA是换行     len equ $ - msg  section .text global _start _start:      mov edx, len     mov ecx, msg     mov ebx, 1 ;文件描述符1 表示std_out标准输出     mov eax, 4 ;write函数系统调用号 4 int 0x80 ;对外输出      mov ebx, 0     mov eax, 1 ;exit函数系统调用号     int 0x80 nasm -f elf hello.asm -o hello.o(编译成为二进制)
 链接:ld -m elf_i386 -o hello hello.o(和其他引用到的类库进行连接,才能生成可执行文件)
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
 官方软件产品操作指南 (170)
官方软件产品操作指南 (170)