Linux进程-2

news2024/9/29 2:32:17

 一:进程优先级

基本概念

cpu资源分配的先后顺序,就是指进程的优先权(priority)。
优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

查看系统进程 ps -la

ps -la命令用于以长格式列出当前系统中所有进程的信息,包括所有用户的进程。-l 选项提供详细的进程信息,而 -a 则表示显示所有进程,包括没有控制终端的进程。

UID : 代表执行者的身份 (跟该程序的持有者 所属组对比,看是否有对应权限)
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
 PRI = 80+NI 
NI :代表这个进程的nice值 [-20,19]

修改优先级

top -> r(进入修改模式) -> 要修改的进程的PID -> 修改后的NI值

PRI=80+NI

[root@hcss-ecs-178e ~]# ps -la
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 30838 30810  0  80   0 - 47970 do_wai pts/1    00:00:00 su
4 S  1001 30839 30838  0  80   0 - 28887 do_wai pts/1    00:00:00 bash
0 S  1001 30860 30839  0  80   0 -  1054 hrtime pts/1    00:00:00 myexe
1 S  1001 30861 30860  0  99  19 -  1054 hrtime pts/1    00:00:00 myexe
4 R     0 30894 30862  0  80   0 - 38332 -      pts/2    00:00:00 ps

二:进程切换

1. 什么是进程切换?

进程切换是指 CPU 停止执行当前进程,并将控制权转移到另一个进程的过程。这种机制使得操作系统能够在多任务环境中并发运行多个进程。

2. 进程切换的原因

时间片到期:当某个进程的时间片用完时,调度器会选择其他进程。

I/O 操作:进程请求 I/O 操作时,会被阻塞,操作系统会切换到其他可运行的进程。

3. 如何进行切换的

首先结构体指针current会指向目标task_struct

pc(程序计数器)内数据是下一条指令的地址,ir(指令寄存器)内数据是目前要执行的指令内容。

1.控制器读取PC中的地址。

2.从内存中获取该地址对应的指令,并将其放入IR中。

3.PC自增,指向下一条指令的地址。

4.控制器执行IR内指令。

5.不断循环直到进程结束或停止。

那这些数据哪里来的呢?如果执行到一半,该第二个进程执行,那这些数据怎么办呢?

其实这些相关寄存器的内容会被存入task_struct(PCB)中,等到再执行到它的时候,再把数据拷贝回PCU的寄存器中,就可以继续运行。

三:Linux2.6内核进程调度队列

CPU的调度顺序是按照队列的顺序从头到尾变量一遍吗?那优先级体现在那呢?

runqueue

runqueue调度队列中有两个指针*active *expired,他们各自指向一个结构体struct queue array

,array中有

1.queue[140]: 一个元素就是一个进程队列。

下标0~99是实时优先级(不关心)(实时优先级使用 SCHED_FIFO 和 SCHED_RR 策略,优先级高的实时任务会优先获得 CPU,实时任务可以抢占普通任务。)

下标100~139是普通优先级(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)

task_struct优先级越高,下标越小。优先级相同的串在同一个位置,类似哈希桶那样。

2.int nr_active 代表队列中有多少个进程

3.int bit_map[5] 用来快速查找进程位置

活动队列 过期队列

*active指向的就是活动队列,*expried指向的就是过期队列。

为什么要有两个队列呢?
1.活动队列中就是要将要调度的进程,如果该进程运行退出了/时间片到了,或者又有新的进程出现了,要重新插到活动队列里吗?随便插就不能叫队列了,尾插优先级就体现不出来了。

2.所以我们一般这3种情况的进程按优先级大小插入到过期队列中。

3.当我们活动队列中nr_active==0时说明已经没有进程了,之后swap(&active,&expried),通过交换指针的对象来改变活动队列 过期队列,保证活动队列只出不进,过期队列只进不出。

快速查找队列中进程

int bit_map[5] 用来快速查找进程位置,这是怎么做到的呢?

5 int = 20 字节 = 160 bit 可以满足140个进程

每一个bit位代表一个进程,存在1 不存在0。

遍历数组,一次性就可以看32个位置存不存在进程。

1.为0说明没有进程

2.不为0有进程,下面代码可以查一个数的二进制中有几个1

int count_set_bits(int x) {
    int count = 0;
    while (x) {
        count++;
        x &= (x - 1);
    }
    return count;
}

这是因为 x - 1 会将 x 的最低位的“1”变为“0”,并将其右侧的所有位(如果有的话)变为“1”。然后,使用按位与(&)操作符,xx - 1 结合后,最低的“1”位被清除。

举个例子:

假设 x = 12,它的二进制表示为 1100

  1. 计算 x - 1

    • x - 1 = 11,二进制为 1011
  2. 按位与操作

    x = 1100 ;x - 1 = 1011  x &= (x - 1) = 1000

补充:为什么进程可以在不同队列中

一般队列中的元素都是包含 数据data 指向下个元素指针struct node*next,

而在struct task_struct这个结构体中,有多个队列 struct node link struct node queuenode...

里面的成员只有指向下个元素的指针struct node*next,而这个元素是struct task_struct的成员变量。知道成员变量地址,就可以算出该结构体首地址,进而随便访问它的成员变量。

成员变量地址-该成员变量的偏移量=struct task_struct的首地址。

offsetof(结构体名, 成员变量名) 

  • &(((type *)0)->member):通过解引用该指针获取成员的地址。

四:命令行参数

什么是命令行参数

命令行参数是用户在运行程序时通过命令行界面传递给程序的输入值。这些参数通常用于配置程序的行为或提供必要的数据。

eg. ls -l -a 

ls指令后面的-l -a 就是命令行参数

这段代码可以打印出命令行参数

argc代表参数个数,argv[] 里面是以空格分开是字符串

根据参数列表的不同,同一个程序可以实现出不同的功能。

eg.ls -a       ls -l

谁传给main函数参数列表的?

参数是由操作系统在程序启动时传递的,当用户在命令行中运行程序时,操作系统会解析命令行并将参数传递给程序。

五:环境变量

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

查看环境变量

1.通过main函数第三个参数

env[0]:XDG_SESSION_ID=354
env[1]:HOSTNAME=hcss-ecs-178e
env[2]:SHELL=/bin/bash
env[3]:TERM=xterm
env[4]:HISTSIZE=10000
env[5]:SSH_CLIENT=121.36.59.153 43740 22
env[6]:OLDPWD=/root
env[7]:SSH_TTY=/dev/pts/0
env[8]:USER=wws
env[9]:LD_LIBRARY_PATH=:/home/wws/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
env[10]:LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
env[11]:PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
env[12]:MAIL=/var/spool/mail/root
env[13]:PWD=/home/wws
env[14]:LANG=en_US.UTF-8
env[15]:HISTCONTROL=ignoredups
env[16]:HOME=/home/wws
env[17]:SHLVL=2
env[18]:LOGNAME=wws
env[19]:SSH_CONNECTION=121.36.59.153 43740 192.168.15.237 22
env[20]:LESSOPEN=||/usr/bin/lesspipe.sh %s
env[21]:XDG_RUNTIME_DIR=/run/user/0
env[22]:HISTTIMEFORMAT=%F %T wws 
env[23]:_=./myexe

2.env指令

env   查看所有环境变量

3.echo $环境变量名

在 Linux 中,echo $环境变量名 命令用于显示环境变量的值。

[wws@hcss-ecs-178e ~]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

4.getenv函数

#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *path = getenv("PATH");  // 获取 PATH 环境变量
    if (path != NULL) {
        printf("PATH: %s\n", path);
    } else {
        printf("环境变量 PATH 不存在。\n");
    }
    
    return 0;
}

头文件#include<stdlib.h> 找到返回指向该变量值的指针,找不到返回NULL

5.environ全局变量

environ 是一个全局变量,其类型通常定义为 char **environ,表示指向字符指针的指针。

#include <stdio.h>
#include <stdlib.h>

extern char **environ;  // 声明 environ

int main() {
    // 打印所有环境变量
    for (char **env = environ; *env != 0; env++) {
        printf("%s\n", *env);
    }
}

常见的环境变量

1.PATH 

PATH是一个环境变量,它指定了系统查找可执行文件的目录。

如果我们运行程序时没有加路径就会在PATH的路径下查找。eg. ls

通常是由多个路径组成,以冒号为分隔符。

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

如果我们自己写的程序不想加路径就运行,1.可以把程序move到默认路径下。

2.可以在PATH中添加我们程序所处的路径。PATH=$PATH:新增路径

                                                                      $PATH是原本的路径

[wws@hcss-ecs-178e ~]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[wws@hcss-ecs-178e ~]$ pwd
/home/wws
[wws@hcss-ecs-178e ~]$ PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[wws@hcss-ecs-178e ~]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

但当我们重新登录的时候却发现PATH中没有我们新增的路径,这是为什么?
我们要知道PATH等环境变量的内容是从系统的配置文件中获取的,在家目录下找到.bash_profile文件(用于设置环境变量、启动程序及其他一次性配置。)在里面添加自己的路径就可以保存下来。

source ~/.bashrc命令让它立即生效。

2.HOME

HOME的内容代表家目录路径,也就是用户一开始登录的路径。

[wws@hcss-ecs-178e ~]$ echo $HOME
/home/wws
[wws@hcss-ecs-178e ~]$ su -
Password: 
Last login: Thu Sep 26 19:25:10 CST 2024 from 121.36.59.153 on pts/0
[root@hcss-ecs-178e ~]# echo $HOME
/root

根据用户的不同,系统设定的HOME也不同,所以用户就能根据自己的HOME找到自己的家目录。

3.SHELL

 查看当前使用的 shell:

[wws@hcss-ecs-178e ~]$ echo $SHELL
/bin/bash

4.PWD

获取当前工作目录

[wws@hcss-ecs-178e ~]$ echo $PWD
/home/wws

5.USER

当前用户

[wws@hcss-ecs-178e ~]$ echo $USER
wws

根据比对USER是否相同,程序就可以实现让特定用户来执行。

6.OLDPWD

上一次所处的路径

[wws@hcss-ecs-178e ~]$ echo $OLDPWD
/root

cd ~

本地变量

set

[wws@hcss-ecs-178e ~]$ a=1
[wws@hcss-ecs-178e ~]$ b=2
[wws@hcss-ecs-178e ~]$ echo $a
1
[wws@hcss-ecs-178e ~]$ echo $b
2

定义的本地变量用env是查不到的,可以用set查看所有环境变量+本地变量

export

将本地变量变为环境变量。

也可以直接设置环境变量 export a=1

bash中有环境变量表 本地变量表,但只有环境变量表可以传给子进程,本地变量表不能,可以把本地变量变为环境变量再传给子进程。所以环境变量有全局属性(环境变量可以在父进程和子进程之间传递信息)

unset

可以删除环境/本地变量

[wws@hcss-ecs-178e ~]$ unset a
[wws@hcss-ecs-178e ~]$ echo $a
 

六:进程地址空间

上图是进程的地址空间的划分,这和我们之前C++内存区域划分是不是有点像呢?它们间有什么联系吗?

什么是进程地址空间

#include<stdio.h>
#include<unistd.h>
int g_val = 0;
int main()
{
    printf("begin.....%d\n",g_val);
    pid_t id = fork();
    if(id==0)
    {
        //child
        int count = 0;
        while(1)
        {
    		printf("child: pid: %d,ppid: %d, g_val:%d, &g_val: %p\n",getpid(),getppid(),g_val,&g_val);
            sleep(1);
            g_val++;
        }
        
    }
    else if(id>0)
    {
        //father
        while(1)
        {
             printf("father: pod: %d,ppid: %d, g_val:%d, &g_val: %p\n",getpid(),getppid(),g_val,&g_val);
            sleep(1);
        }
       	
    }
    return 0;
}

上面代码子进程对全局变量++,父进程不改变全局变量。

可以看到子进程读取g_val时它的值一直变化,而父进程读取g-val永远是0,但是父子进程取得g_val的地址都是一样。这个地址是物理地址吗?
不是,它是一种虚拟地址。是进程空间地址

进程空间地址的本质是一种结构体struct mm_struct,里面包含了不同区域的范围。

记住堆区的开始和结束地址,中间的都是可以用的。

struct mm_struct
{
    unsigned long code_start;//代码区
    unsigned long code_end;
    
    unsigned long init_start;//初始化区
    unsigned long init_end;
    
    unsigned long uninit_start;//未初始化区
    unsigned long uninit_end;
    
    unsigned long heap_start;//堆区
    unsigned long heap_end;
    
    unsigned long stack_start;//栈区
    unsigned long stack_end;
    //...等等
}

每一个进程都有一个虚拟地址,struct_task中成员变量有指向mm_struct的指针。

在内存中不止存有一个程序的资源,每个进程都有自己的虚拟地址,而虚拟地址的作用就是让每一个进程认为自己可以独享所有内存空间。

比如说进程申请空间,在虚拟地址中标记0x1111~0x2222的空间被申请,实际上在物理地址不一定是0x1111~0x2222,可能是在其它地方。虚拟地址栈区中有4G空间,但实际在物理地址中可能只有2G,这样进程申请3G空间,就会被系统拒绝。

页表

上述虚拟地址和物理地址中间是怎么联系的?
其实是根据页表产生联系的,页表是操作系统中用于管理虚拟内存的一种数据结构,它负责维护虚拟地址与物理地址之间的映射关系。

当进程访问某个变量,它在、的虚拟地址是0x1111,而物理地址是0x2222,页表的作用就是将进程使用的虚拟地址转换为物理地址。

fork()创建子进程,子进程的task_struct mm_struct 页表都是以父进程为模板创建的,所以指向同一段代码,如果子进程对数据进行修改g_val++ ,内存就会再开辟一块空间存放子进程的g_val,子进程页表映射就指向新开辟的空间。也就是写时拷贝

printf打印的就是虚拟地址,而系统真正访问的是物理地址,所以值会不一样。

标志位

在页表中处理了虚拟地址和物理地址外,还有一些标识符,那标志位有什么用?

1.读/写位(Read/Write Bit):

指示该页面是可读的还是可写的。如果该位为0,表示该页面为只读;如果为1,表示可以进行读写操作。

当我们对一个变量进行修改时,先看在页表中是否有对应的映射关系,如果有看是否有写权限,有就修改,反之终止进程。

就像char*str="111" *str="222",对它进行修改编译时不会进行权限检查,所以不会报错,运行时就会终止。也因此出现了const

2.存在位(Present Bit)

页面是否在物理内存中。如果该位为0,表示该页面不在内存中,可能需要从磁盘加载。

当程序从磁盘加载到内存中,不是一次性加载而是分批加载,访问时在页表中有映射关系并且存在位为1,才能访问。如果为0,要等数据从磁盘中加载到内存把存在位变1.

进程地址空间区域范围划分

每个程序都有自己的进程空间,大小不一样,进程空间的代码区等范围也是不一样的。mm_struct本质就是结构体变量,也需要初始化。那么它是根据什么进行初始化划分代码区,栈区 堆区等的范围的呢?

1.首先可执行程序除了代码和数据还包含属性,里面就有代码区范围的大小,变量权限是否可读写。

mm_struct的代码区范围就是从可执行程序的属性中读取。

2.栈区 堆区 命令行参数环境变量 这些程序编译的时候并不会创建,他们是由操作系统动态生成并管理的。当进程被创建时,操作系统会为其分配一个默认的栈/堆大小,函数开辟栈帧改变栈区大小,malloc/free会改变堆区大小

此时改变的mm_struct中堆区范围大小,在物理内存上并没有进行开辟,当对申请的空间使用时,才会在物理内存上开辟。确保物理内存中开辟的空间都在使用

为什么要有进程空间地址

1. 内存隔离

个进程都有独立的地址空间,这样可以防止一个进程访问或修改另一个进程的内存数据。

对内存进行修改时,要查看是否有对应权限才能修改。防止野指针随便修改内容

2.进程管理和内存管理在系统层面上解耦合

创建进程时可以先在进程空间上进行操作,等真正使用数据时再写入内存空间中。

3.让进程以统一的视角看待物理内存

每个进程在操作系统中都有自己独立的虚拟地址空间。这意味着每个进程都可以以统一且一致的方式访问其内存,而不必担心其他进程的内存内容。通过页表映射即使在物理内存中无序放置数据,也可以快速找到

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

9_28代码实现登录框 注释

注释&#xff1a; .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> // 防止头文件重复包含QT_BEGIN_NAMESPACE namespace Ui { class Widget; } //Ui表示命名空间的名称 //{ class Widget; } &#xff1a;表示在Ui命名空间中声明一个其他文件midget的类 QT_…

前段辅助工具分享(像素大厨)

引言&#xff1a; 我们在从事前端开发工作时&#xff0c;常会需要测量许多盒子的尺寸&#xff0c;颜色提取种种&#xff0c;切图&#xff0c;还有文字大小等信息&#xff0c;光从肉眼很难看出来&#xff0c;当然我们传统的会使用Photoshop来帮助我们完成这些工作&#xff0c;但…

LeetCode[中等] 17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 思路 回溯法 log&#xff1a;当前结果数组&#xff1b;level&#xff1a…

How to install JetBrains ToolBox in Ubuntu 22.04 LTS?

JetBrains Toolbox 的安装教程 在 2024 年 9 月 28 日&#xff0c;我想和大家分享一下 JetBrains Toolbox 的安装步骤&#xff0c;让你轻松开启高效的开发之旅。 一、准备工作 首先&#xff0c;确保你已经准备好了要安装的 JetBrains Toolbox 文件&#xff0c;可以从官方网站…

想入职网络安全?小白必看面试题(进阶版)(最终章)

大家好&#xff0c;我是Dest1ny&#xff01; 有同学问我为什么还要发面试题目。 因为我忘记发了。。。 这是最后一点面试题&#xff0c; 给大家发完&#xff01; Java基础 1. ★★☆☆☆ equals与的区别 比较引用是否相同&#xff0c;equals() 比较内容是否相同。 2. ★★…

MATLAB编写的RSSI在三维空间上的定位程序,锚点数量无限制(可自定义),带中文注释

文章目录 程序说明功能概述环境设置结果可视化函数定义运行结果程序获取 程序说明 功能概述 该程序实现了在三维空间中通过接收信号强度指示&#xff08;RSSI&#xff09;进行定位的功能。利用多个锚节点的信号强度测量&#xff0c;估计未知点的位置。该程序适用于无线定位应…

【深度学习】—线性回归 线性回归的基本元素 线性模型 损失函数 解析解 随机梯度下降

【深度学习】— 线性回归线性回归的基本元素 线性模型损失函数解析解随机梯度下降小批量随机梯度下降梯度下降算法的详细步骤解释公式 线性回归 回归&#xff08;regression&#xff09;是能为⼀个或多个⾃变量与因变量之间关系建模的⼀类⽅法。在⾃然科学和社会科学领域&…

【MYSQL】授权远程连接的用户

文章目录 一、Navicat新建查询1.点击新建查询&#xff0c;授权远程连接的用户语句&#xff1a;2.刷新权限 二、Navicat用户 一、Navicat新建查询 1.点击新建查询&#xff0c;授权远程连接的用户语句&#xff1a; GRANT ALL PRIVILEGES ON *.* TO 库的用户名授权IP IDENTIFIED …

注册器设计模式,以SparseInst(detectron2)代码为例

注册器设计模式 from detectron2.utils.registry import Registry 这里面的Registry实际上就是注册器设计模式 1.举一个简单版的小例子来理解注册器设计模式 参考&#xff1a;Python注册器设计模式_python 注册类-CSDN博客 # 这一行代码是从Python的 typing 模块中导入了一些…

3分钟教程,手把手教你使用腾讯元宝定制属于自己的AI助手

在今天这个市场&#xff0c;竞争激烈的不得了&#xff0c;大家每天都必想的问题是啥&#xff1f;是“降本增效”&#xff0c;都在想把一个人当两个人用&#xff01; 但老板有秘书&#xff0c;领导有员工&#xff0c;作为牛马的我呢&#xff1f;我左顾右盼之后发现背后空荡荡的…

大数据毕业设计选题推荐-重庆旅游景点数据分析系统-Python-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

JavaScript网页设计案例:互动式简历网站

JavaScript网页设计案例&#xff1a;互动式简历网站 在现代网页设计中&#xff0c;JavaScript 是实现交互和动态效果的关键技术。本文将通过一个完整的案例&#xff0c;展示如何使用 JavaScript 构建一个交互式的个人简历网页。本文不仅会涵盖 HTML 和 CSS 的使用&#xff0c;…

机器学习:探索未知边界,解锁智能潜力

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 在这个日新月异的科技时代&#xff0c;机器学习作为人工智能领域的核心驱动力&#xff0c;正以前所未有的速度改变着我们的世界。从智能家居的个性化推荐到自动驾驶汽车的精准导航&#xff0c;从医疗诊断的辅助…

【数据结构与算法】基本概念

数据结构与算法——绪论 文章目录 一.数据结构的研究内容1.1数值计算1.2非数值计算 二.基本概念和术语2.1数据&#xff0c;数据元素&#xff0c;数据项和数据对象2.2数据结构2.2.1逻辑结构2.2.2存储结构&#xff08;物理结构&#xff09;2.2.3运算和实现 三.抽象数据类型的表示…

安装管理K8S的开源项目KubeClipper介绍

安装管理K8S的开源项目KubeClipper介绍 1. 概述 KubeClipper是九州云开源的一个图形化界面 Kubernetes 多集群管理工具&#xff0c;旨在提供易使用、易运维、极轻量、生产级的 Kubernetes 多集群全生命周期管理服务。让运维工程师从繁复的配置和晦涩的命令行中解放出来&#…

VMware下的ubuntu显示文字太小的自适应显示调整

我的情况 我使用的是4K的32寸显示器&#xff0c;分辨率为 3840 x 2160&#xff0c;ubuntu版本为18.04&#xff0c;默认的情况下系统分辨率为 3466 x 1842。 ​ 此时&#xff0c;显示的文字很小&#xff0c;虽然可以看清&#xff0c;但也比较吃力&#xff0c;在VMware窗口…

深入探索机器学习中的目标分类算法

在当今数据驱动的世界中&#xff0c;机器学习&#xff08;Machine Learning, ML&#xff09;正逐渐成为解决问题的重要工具。在众多机器学习任务中&#xff0c;目标分类&#xff08;Classification&#xff09;算法尤其受到关注。本文将深入探讨目标分类算法的基本概念、常见类…

828华为云征文|部署开源超轻量中文OCR项目 TrWebOCR

828华为云征文&#xff5c;部署开源超轻量中文OCR项目 TrWebOCR 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 TrWebOCR3.1 TrWebOCR 介绍3.2 TrWebOCR 部署3.3 TrWebOCR…

解压视频素材下载网站推荐

在制作抖音小说推文或其他短视频时&#xff0c;找到合适的解压视频素材非常重要。以下是几个推荐的网站&#xff0c;可以帮助你轻松下载高质量的解压视频素材&#xff1a; 蛙学网 蛙学网是国内顶尖的短视频素材网站&#xff0c;提供大量4K高清无水印的解压视频素材&#xff0c;…

C++:STL(四)之vector的基本介绍与使用方式|容器接口

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山冈&#xff01; &#x1f525; 所属专栏&#xff1a;C深入学习笔记 &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 一、C/C中的字符串 1.1. C语言中的…