【Linux第五课-进程上】PCB内部属性、标识符、进程状态、Linux下的进程状态、进程的优先级、Linux进程的调度与切换

目录

  • 体系结构 -- 硬件上
  • 操作系统 -- 软件上
  • 进程
    • PCB内部属性
      • 1、在linux里面看程序
      • 2、标识符
        • 获取程序的标识符
        • 父进程标识符 PPID
        • 查看进程的另一种方法
        • 通过系统调用创建进程 - fork
          • 杀掉一个进程
          • for循环创建多个代码
      • 3、进程状态
        • 进程排队 - 队列
        • 教程上关于进程状态表述
          • 运行
          • 阻塞
          • (阻塞)挂起
        • Linux下的具有进程状态
        • R(running)运行状态
        • S(sleep)睡眠状态
        • D(Disk sleep)磁盘休眠状态
        • t(stopped)暂停状态
        • T(tracing stop)暂停状态
        • Z(zombie)僵尸状态
          • 孤儿进程
        • X(dead)死亡状态
        • 信号
    • 进程的优先级
      • 是什么?
      • 为什么存在优先级
      • 调整优先级
    • Linux的调度与切换
      • 概念
      • 进程切换
      • 进程调度
    • PCB外部,整体使用

体系结构 – 硬件上

1、冯诺依曼体系结构
在这里插入图片描述
独立
CPU:运算器(算数和逻辑运算)+控制器(协调CPU内部之间 信息流动)
输入设备:话筒、摄像头、键盘、鼠标、磁盘、网卡等
输出设备:声卡、显卡、网卡、磁盘、显示器、打印机等
有的设备只做输入,只做输出,有的即做输入又做输出
存储器:内存(掉电易使)
设备是链接的:总线(主板)链接起来
链接不是目的,是手段。目的是设备之间的数据流动(本质:设备之间会进行数据的来回拷贝)

操作系统 – 软件上

进行软硬件管理的软件
在这里插入图片描述

什么时候读、什么时候写、都多少、写多少是操作系统管的
对任何事务做管理:先描述,在管理

操作系统给用户提供一系列的系统调用接口对操作系统内部的数据进行访问,不允许用户直接访问操作系统内部数据

系统调用接口,就是C语言设计的函数,系统调用函数(函数就有输入和输出)
操作系统给用户提供:数据方面的支持、功能方面的支持

进程

教材观点:
加载到内存的程序 – 进程
正在运行的程序

事实
(1)我们可以启动多个程序(每个程序都有一个exe) — 我们将多个exe加载到内存
(2)操作系统需要管理多个加载到内存的程序
(3)操作系统如何管理加载到内存的程序?先描述,在组织
一个加载到内存的程序我们称为进程

struct xxx
{//状态//优先级//内存指针字段//标识符//……包含进程几乎所有的属性字段struct xxx* next;
}

上述的描述进程的结构体,我们称为PCB(process ctrl block)进程控制块

struct PCB
{//状态//优先级//内存指针字段//标识符//……包含进程几乎所有的属性字段struct PCB* next;
}

对进程的管理转换成对PCB对象的管理,也就是对链表的增删查改

进程 = 内核PCB对象(内核数据结构) + 可执行程序

PCB,操作系统学科的叫法
具体的linux,PCB称为task_struct,操作系统内部的数据

PCB内部属性

1、标识符
2、状态
3、优先级
4、程序计数器:程序中即将要被执行的指令的地址
5、内存指针:找到代码和数据的指针
6、I/O状态信息:
7、记账信息

1、在linux里面看程序

创建myprocess.c
在这里插入图片描述
创建Makefile
在这里插入图片描述
运行程序

第一条程序是myprocess进程
第二条程序是grep本身是一个指令,也就是一个程序,它是包含myprocess
几乎所有的独立的指令,就是程序,运行起来也要变成进程
在这里插入图片描述
看进程结束的过程

while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done

在这里插入图片描述

1、只有打印到显示屏上的内容才能被重定位和追加重定位
(1) '>':重定向
(2)‘>>’:追加重定向
blog.csdnimg.cn/direct/91879d6b99a14e19b5761449f2343282.png)
在这里插入图片描述
2、‘echo’:后面跟着string直接打印string,后面跟着$sht则打印变量sht的值
3、'|':表示管道,上一条命令的输出,作为下一条命令参数进行传递,如:ls | grep “aa”,在ls的输出中查找aa字符串。
4、'head':打印一个文件的前多少行
(1)head:默认打印前十行
(2)head -n:打印前n行
5、&&:表示前一条命令执行成功时,才执行后一条命令 ,如 echo '1‘ && echo ‘2’
在这里插入图片描述
6、grep
(1)grep xxx:过滤出来包含xxx的
(2)grep -v grep:反向过滤,不把含义grep的过滤出来
在这里插入图片描述

2、标识符

PID就是标识符

ps axj

COMMAND代表你这个进程在启动的时候对应的可执行程序是谁
在这里插入图片描述

获取程序的标识符

函数调用

getpid

man getpid
在这里插入图片描述

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 5 int main()6 {7     pid_t id = getpid();8     printf("%d\n", id);9     printf("hello zyh\n");10     return 0;                                                                 11 }

在这里插入图片描述

在Linux中,普通进程,一般都有父进程

父进程标识符 PPID
getppid

在这里插入图片描述

  1 #include<stdio.h>                                                             2 #include<unistd.h>3 #include<sys/types.h>4 5 int main()6 {7     pid_t id = getpid();8     pid_t fid = getppid();9     printf("id:%d\n", id);10     printf("fid:%d\n", fid);11     printf("hello zyh\n");12     return 0;13 }

每一次启动进程的pid都会变化,因为我们每次启动的都是一个新进程

其中bash就是命令行解释器
在这里插入图片描述

查看进程的另一种方法

ls
-l 参数 以详细格式列表
-d 参数 仅列当前目录本身

通过/proc系统文件夹进行查看
在这里插入图片描述
当我们要查看某特定进程
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

为何删了之后还能正常运行,因为程序正在运行被加载到了内存,删除磁盘上的可执行程序没有影响
cwd是当前工作目录

fopen(“./文件名”, “w”);
如果没有此文件就在当前路径下创建
改变当前的工作目录:chdir()
在这里插入图片描述
在这里插入图片描述

当前路径:当前进程所在的路径cwd
在这里插入图片描述

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 5 int main()6 {7     pid_t pid = getpid();8     printf("pid: %d\n", pid);9 10     FILE *fp = fopen("./zyh.txt","w");11     if(fp == NULL) return 0;12     printf("zyh.txt文件创建成功!\n");                                        13     fclose(fp);14     sleep(20);15     return 0;16 }

如果进程的所在路径cwd被修改,那么文件也会被创建在修改后的路径
改变当前的工作目录:chdir()
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 5 int main()6 {7     pid_t pid = getpid();8     printf("pid: %d\n", pid);9     sleep(20);10     printf("修改当前路径\n");11     chdir("/home/hui");                                                       12     printf("修改当前路径成功\n");13     sleep(20);14     FILE *fp = fopen("./zyh.txt","w");15     if(fp == NULL) return 0;16     printf("zyh.txt文件创建成功!\n");17     fclose(fp);18     sleep(20);19     return 0;20 }
通过系统调用创建进程 - fork

在这里插入图片描述
对于fork的返回:对于父进程返回创建进程的id,对于子进程返回0

在这里插入图片描述
在这里插入图片描述

一般而言,我们想让父子做不同的事情
pid都是大于等于0的数字

父进程先被创建了
在这里插入图片描述
此时子进程也被创建了
在这里插入图片描述
在这里插入图片描述

进程 = 内核数据结构 + 可执行程序的代码和数据
创建子进程时,是以父进程为模板的。内核数据结构大部分和父进程一样,但也有些少部分不一样(如,pid、ppid)

(1)fork为何会返回两个值为什么会这样?
把子进程的pid返回给父进程,目的是方便父进程对子进程的控制和唯一性确认。子进程不需要这些,只需要知道创建成功没成功,因此返回0就可以了(父:子 = 1:n,子进程找父进程是唯一的,父进程找子进程就需要pid)
(2)fork为何会返回两次?
如果一个函数,已经运行到了return的时候,说明这个函数的核心逻辑已经做完了
在调用fork函数的时候,运行到return这条语句之前,子进程就已经被创建,因此return id这条语句是同时被父进程和子进程执行的
在这里插入图片描述

(3)id怎么可能同一个变量,既大于0,又等于0

一个进程崩溃了,不会影响其他进程
进程(任意)之间是具有独立性的,互相不受影响。(os在设计的时候就必须保证的)

杀掉一个进程
kill -9 进程id

在这里插入图片描述
在这里插入图片描述

linux中可以使用同一个变量名,表示不同的内存
当代码被编译成二进制,代码中的变量名就不在了

for循环创建多个代码
  1 #include <stdio.h>2 #include <unistd.h>3 #include <stdlib.h>4 #include <sys/types.h>5 const int num = 10;6 7 void work()8 {9     int x = 10;10     while(x > 0)11     {12         printf("I am a child process, my id: %d\n",getpid());13         sleep(1);14         --x;15     }16 }17 18 int main()19 {20     for(int i = 0; i < num; i++)21     {22         pid_t id = fork();23         sleep(1);24         if(id < 0) break;                                             25         else if(id == 0)26         {27             //子进程28             work();29             exit(1);30         }31         //父进程32         printf("creat %d child process, subid:%d\n", i, id);33     }34     sleep(20);35     return 0;36 }

正在创建子进程
在这里插入图片描述
正在杀死子进程
在这里插入图片描述

3、进程状态

进程排队 - 队列

进程排队一定是在等待某种资源

进程不是一直在运行的,进程放在CPU上,也不会一直运行 — 时间片
排队:是进程的task_struct在排队

Linux中进程pcb的排序
在这里插入图片描述

教程上关于进程状态表述

运行、阻塞、挂起
所谓的状态,就是一个整型变量,再task_struct中的一个整型变量

#define New 1
#define Ready 2
#define running 3
#define block 4

struct task_struct
{int status;……
}
运行

把进程的PCB放到一个CPU的运行队列中,我们就称为这个队列的运行状态
在这里插入图片描述

一个CPU一个运行队列

阻塞

在这里插入图片描述
当我们的进程在进行等待软硬件资源的时候,资源如果没有就绪,我们进程的task_struct只能

1、将自己设置为阻塞状态
2、将自己的pcb连入等待的资源提供的等待队列

状态的变换,就是把进程的PCB放到不同的队列中

(阻塞)挂起

在这里插入图片描述

挂起状态
前提:计算机资源(eg:内存资源)已经比较吃紧了
阻塞挂起:当进程在阻塞的状态下,资源吃紧了,操作系统就会把阻塞进程的代码和数据从内存写回到磁盘的swap分区

进程的PCB(task_struct)不会换出
创建进程时先创建对应进程的PCB(内核数据结构)

Linux下的具有进程状态

在这里插入图片描述

R(running)运行状态

并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
在这里插入图片描述

代码在运行为何显示是S,因为代码里面只有一行printf,printf导致进程大部分时间都在等待
在这里插入图片描述
把进程改成一个死循环就是R状态了
在这里插入图片描述
在这里插入图片描述

+”:是指这个进程在前台,运行此进程时,无法执行其他命令
./myprocess &后台进程
(1)后台进程ctrl+c无法杀掉,只能kill -9 进程id

前台进程
在这里插入图片描述
后台进程
在这里插入图片描述

S(sleep)睡眠状态

意味着进程在等待事件完成,也就是一种阻塞状态,Linux中也称为浅度睡眠

ctrl+c可以结束进程

在这里插入图片描述

D(Disk sleep)磁盘休眠状态

称为不可中断睡眠,又称深度睡眠D状态也是阻塞状态,有些进程执行的内容很重要,操作系统不能把它杀死

t(stopped)暂停状态

让进程处于暂停状态,当某些进程操作比较危险,操作系统会将其暂停。也是阻塞状态
(1)程序开始运行,创建了进程此时进程是前台进程
在这里插入图片描述
(2)kill -9 进程id对进程进行暂停
在这里插入图片描述
(3)kill -19 进程id对进程进行启动,再次启动的进程有前台进程变为后台进程

在这里插入图片描述

T(tracing stop)暂停状态

进程处于被追踪状态,等待gdb给的控制命令,gdb不让进程跑了。也是阻塞状态
(1)在生成可执行程序的时候注意加-g
在这里插入图片描述
(2)进入gdb; l + 行号:从第几行开始显示代码
在这里插入图片描述
(3)p:打断点; r:运行到断点
此时的进程就是t状态,等待gdb的下一步指令
在这里插入图片描述

Z(zombie)僵尸状态

也是终止状态,当进程完成时或发生意外,代码和数据可以释放,但进程的PCB不能被释放,父进程或操作系统还需要去读其退出信息

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>int main()
{pid_t id = fork();//子进程if(id == 0){int cnt = 5;while(cnt){printf("I am child, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);cnt--;}exit(0); //子进程退出}//只有父进程,父进程一直死循环就不会读取子进程的退出信息,子进程就处于僵尸状态while(1){printf("I am father, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);}return 0;
}

在这里插入图片描述

为何会有Z状态?
创建进程是希望这个进程给用户完成工作的,子进程必须有结果数据,PCB中的。
什么是Z?
进程已经退出,但当前进程的状态需要自己维持住,供上层读取,必须处于Z
如果父进程就不读取?
僵尸状态会一直存在,task_struct对象也要一直存在,都是要占据内存的。内存泄漏
最初创的进程的父进程是bash,会自动回收退出信息,如果在自己创建的进程下面再fork一个子进程,此时子进程的父进程不会自动回收退出信息

bash进程会自动读取其下面子进程的退出信息,但这里创建的father进程不会自动读出子进程的退出信息
在这里插入图片描述
在这里插入图片描述

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>int main()
{pid_t id = fork();//子进程if(id == 0){int cnt = 5;while(cnt){printf("I am child, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);cnt--;}exit(0); //子进程退出}//只有父进程,父进程一直死循环就不会读取子进程的退出信息,子进程就处于僵尸状态int cnt = 10;while(cnt){printf("I am father, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);cnt--;}//父进程读取子进程的退出信息wait(NULL);printf("father wait child done...\n");sleep(5);
孤儿进程

一个进程的父进程先退出了,那该进程会被1号进程领养,1号进程是操作系统

一个进程被领养后,不仅变成孤儿进程,还会变成后台进程

在这里插入图片描述

    pid_t id = fork();//子进程if(id == 0){while(1){printf("I am child, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);cnt--;}//exit(0); //子进程退出}//只有父进程,父进程一直死循环就不会读取子进程的退出信息,子进程就处于僵尸状态int cnt = 10;while(cnt){printf("I am father, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);cnt--;}
X(dead)死亡状态

终止状态,是一个瞬时状态很难查到

信号
kill -l

9:SIGKILL
19:SIGSTOP
18:SIGCONT
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

进程的优先级

是什么?

前提:进程要访问某种资源,进程通过一定的方式(排队),确认享受资源的先后顺序

优先级和权限的区别
优先级:你先还是我先的问题
权限:能不能的问题

为什么存在优先级

资源过少,相对的概念
PRI (Priority):进程的优先级

linux的优先级在进程运行中或运行前是可以被修改的,优先级范围[60,99]–>40
nice值为**[-20, 19]**
数字越小优先级越高

在这里插入图片描述

调整优先级

1、top进入任务管理器
2、r(renice)-> 输入对于pid -> 要修改的nice -> q退出
输入r之后的界面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Linux系统允许用户调整优先级,但是不能直接让修改pri,而是修改nice值
nice:进程优先级的修正数据[-20, 19]
pri = pri(old) + nice pro(old)每次都是80

为何优先级调整在60-99之间
如果不加限制,将自己进程的优先级调整的非常高,别人的优先级调成非常低
优先级较高的进程,优先得到资源,后面还有源源不断的进程产生。常规进程很难享受到CPU资源 — 进程饥饿

Linux的调度与切换

概念

1、进程在运行的时候,放在CPU上,直接必须把进程跑完,才行吗?
不行,现在操作系统都是基于时间片进行轮转执行的
2、
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发

进程切换

进程在运行时,会产生大量的临时数据放到CPU的寄存器中

所有的保存都是为了最终的恢复,所有的恢复,都是为了继续上一次的运行位置继续运行。可以认为寄存器里的数据保存在PCB保护上下文
虽然寄存器数据放在一个共享的CPU里面,但是所有的数据,其实都是被进程私有的

CPU内部的所有临时数据,称作进程的硬件上下文
CPU内的寄存器只有一套,寄存器内保存的数据可以有多套

进程调度

Linux实现进程调度的算法,考虑优先级、饥饿、效率

分时操作系统:公平,每个进程在一定时间段内享受到资源。即便有优先级,大家优先级也不明显。eg:互联网买东西,大家优先级都一样
实时操作系统:进程跑起来必须跑完才能跑下一个,必须严格按照顺序跑,有更高优先级的进程允许插队。 eg:做车载系统,一脚油门下去必须立马反应,不能基于时间片慢慢跑

0-99不考虑实时优先级
100-139:这四十个对应着进程的优先级**[60,99]**
在这里插入图片描述

每次从头查数组各个位置是否为空还是很麻烦的int bitmap[5]
32*5=160
比特位的位置,表示哪个队列
比特位的内容,表示该队列是否为空
检测那个队列中是否有进程,检测对应的比特位是否为1

如果一直有高优先级的进程排队就会产生饥饿问题,解决方法:过期进程和活跃进程
CPU从活跃队列选择进程,新来的进程在过期队列
在这里插入图片描述

struct q* activestruct q* expired
CPU只会去活跃队列里面拿进程,当进程运行时间片结束或运行结束或新建进程,操作系统会将其放入到过期队列

struct q* active = &array[0]
struct q* expired = & array[1]

在这里插入图片描述

活跃队列里面的进程不断增多,过期队列中的进程不断减少,对后只需要对active和expired进行交换指针的内容即可

swap(&active, &expired)

PCB外部,整体使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/435218.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Android 14源码分析】Activity启动流程-2

忽然有一天&#xff0c;我想要做一件事&#xff1a;去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…

PingCastle:一款针对活动目录AD的安全强化工具

关于PingCastle PingCastle是一款针对活动目录AD的安全强化工具&#xff0c;可以帮助广大研究人员提升活动目录的安全性&#xff0c;该工具甚至可以做到在 20% 的时间内实现 80% 的AD安全性。 Ping Castle 是一种旨在使用基于风险评估和成熟度框架的方法快速评估活动目录AD 安…

pywinauto,一款Win自动化利器!

1.安装 pywinauto是一个用于自动化Python模块&#xff0c;适合Windows系统的软件&#xff08;GUI&#xff09;&#xff0c;可以通过Pywinauto遍历窗口&#xff08;对话框&#xff09;和窗口里的控件&#xff0c;也可以控制鼠标和键盘输入&#xff0c;所以它能做的事情比之前介…

大数据实时数仓Hologres(一):Hologres 简单介绍

文章目录 Hologres 简单介绍 一、什么是实时数仓 Hologres 二、产品优势 1、专注实时场景 2、亚秒级交互式分析 3、统一数据服务出口 4、开放生态 5、MaxCompute查询加速 6、计算存储分离架构 三、应用场景 搭建实时数仓 四、产品架构 1、Shared Disk/Storage &am…

Appium独立测试自动化初始化脚本

1、查看环境初始化参数 确保appium已经开起来了&#xff0c;设置ip ,并点击启动 打开夜神模拟器&#xff0c;点击工具--设置 最下面的版本说明&#xff0c;双击进去 版本号这里再去单击。 直到进入到开发者模式。 可能我们不是开发者模式打开的状态&#xff0c;所以软件访问模…

我摊牌了!!程序员不卷了,AI大模型先转一步!

计算机行业小伙伴儿们的归宿到底在哪里啊&#xff1f; 互联网和程序员的风口已经过去了&#xff0c;作为一名大龄程序员&#xff0c;在继续卷和转型发展之间我选择了转行AI大模型。 4年更火的无非就是人工智能了&#xff0c;大家在招聘网站也可以看到名种各样的offer&#x…

基于Java+VUE+echarts大数据智能道路交通信息统计分析管理系统的设计与实现

大数据智能交通管理系统是一种基于Web的系统架构&#xff0c;通过浏览器/服务器&#xff08;B/S&#xff09;模式实现对城市交通数据的高效管理和智能化处理。该系统旨在通过集成各类交通数据&#xff0c;包括但不限于车辆信息、行驶记录、违章情况等&#xff0c;来提升城市管理…

天龙八部怀旧单机微改人面桃花+安装教程+GM工具+虚拟机一键端

今天给大家带来一款单机游戏的架设&#xff1a;天龙八部怀旧单机微改人面桃花。 另外&#xff1a;本人承接各种游戏架设&#xff08;单机联网&#xff09; 本人为了学习和研究软件内含的设计思想和原理&#xff0c;带了架设教程仅供娱乐。 教程是本人亲自搭建成功的&#xf…

画个心,写个花!Python Turtle库带你玩转创意绘图!

文章目录 前言一、Turtle 库基础介绍二、画布设置三、画笔属性设置1.画笔颜色设置2.画笔粗细与速度设置3.画笔形状设置 四、画笔移动函数五、画笔控制函数六、实战案例一&#xff1a;“花”字绘制七、实战案例二&#xff1a;心型图案绘制总结 前言 Python 的 turtle 库是一种简…

关于宝塔PHP getenv无法获取环境变量问题解决办法

今天有用ThinkPHP8接入阿里云OSS时&#xff0c;需要用的用到getenv()来读取环境变量&#xff0c;因为新版OSS SDK是用环境变更来设置AK的。 现象 正常执行PHP文件&#xff0c;可以取到环境变量&#xff1b;但是通过nginxphp-fpm调用脚本取到不到环境变量 原因 php-fpm为了防止…

[spring]用MyBatis XML操作数据库 其他查询操作 数据库连接池 mysql企业开发规范 动态sql

文章目录 一. MyBatis XML配置文件1. 配置链接字符串和MyBatis2. 写持久层代码方法定义Interface方法实现xml测试 3. 增删改查增:删改查 二. 开发规范(mysql)三. 其他查询操作1. 多表查询2. #{} 和 ${}(面试题)使用区别 排序功能like查询 三. 数据库连接池四. 动态sql1. < i…

使用shc|gzexe加密shell脚本,并配置全局可用

前言&#xff1a;堡垒机上多厂家共用&#xff0c;导致脚本需要加密并设置过期时间 一、使用shc&#xff08;二进制&#xff09; 1、安装shc sudo yum install epel-release sudo yum -y install shc sudo yum -y instal epel-release && sudo yum -y install shc 2、…

图像增强论文精读笔记-Deep Retinex Decomposition for Low-Light Enhancement(Retinex-Net)

1. 论文基本信息 论文标题&#xff1a;Deep Retinex Decomposition for Low-Light Enhancement 作者&#xff1a;Chen Wei等 发表时间和期刊&#xff1a;2018&#xff1b;BMVC 论文链接&#xff1a;https://arxiv.org/abs/1808.04560 2. 研究背景和动机 低光照条件下拍摄的…

计算机毕业设计 基于 Hadoop平台的岗位推荐系统 SpringBoot+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

tauri开发软件中,使用tauri自带的api用浏览器打开指定的url链接

有能力的可以看官方文档&#xff1a;shell | Tauri Apps 就是使用这个api来打开指定的url链接&#xff0c;要在tauri.config.json中配置打开这个api&#xff1a; 然后在前端页面中导入使用&#xff1a; import { open } from tauri-apps/api/shell; // opens the given URL o…

ODA(Open Design Alliance)试用小记-ODA提供源码下载就完全可控了吗?

1.概述 ODA(Open Design Alliance)库架构如下&#xff1a; 产品体系如下&#xff1a; ODA的产品体系越来越壮大&#xff0c;包括主流BIM格式SDK、Viewer、Cloud、数据交换等&#xff0c;每个模块需要单独购买&#xff0c;并提供“源码服务”。 2.是否可控&#xff1f; 值得…

【rust】 基于rust编写wasm,实现markdown转换为html文本

文章目录 背景转换预览核心代码前置依赖rustup换源 cargo本地路径修改&#xff08;可选&#xff09;cargo换源中科大 wasm-pack安装 背景 尝试用rust编写一款markdown转html的插件&#xff0c;通过wasm给html使用&#xff0c;不得不说体积挺小&#xff0c;约200K&#xff0c; …

深度学习——D2(数据操作)

N维数组 创建数组 访问元素 一列: [ : , 1 ] 反向累积、正向累积&#xff08;自动求导&#xff09; 梯度 梯度&#xff08;Gradient&#xff09;是微积分中的一个重要概念&#xff0c;主要用于描述一个函数在某个区域内的变化情况。以下是对梯度的详细解释&#xff1a; 一…

Qorvo® 推出具有卓越能效的新一代 Matter™ 解决方案

全新 SoC 利用 ConcurrentConnect™ 技术实现智能家居的无缝互联 Qorvo今日宣布&#xff0c;推出面向智能家居设备的全新片上系统&#xff08;SoC&#xff09;解决方案——QPG6200L&#xff0c;并已向主要客户提供样品。该款下一代物联网&#xff08;IoT&#xff09;解决方案采…

数据结构双链表和循环链表

目录 一、循环链表二、双向链表三、循环双向链表 一、循环链表 循环链表就是首尾相接的的链表&#xff0c;就是尾节点的指针域指向头节点使整个链表形成一个循环&#xff0c;这就弥补了以前单链表无法在后面某个节点找到前面的节点&#xff0c;可以从任意一个节点找到目标节点…