并发编程基础知识(一)[进程篇]

2023-11-15

目录

 一.程序的执行方式 

    1.进程是什么东西?   

2.进程与程序区别  

3.进程状态    

4.linux进程地址空间布局   

5.linux下进程相关的API函数  

    (1)创建一个新进程   

    (2)进程退出  

    (3)等待子进程退出 

    (4)让一个进程去执行一个指定的程序文件

    (5)执行指定的程序

                总结:  


 一.程序的执行方式 


    (1)顺序执行  
        一个程序完全执行完毕后,才能执行下一个程序
        假如: 一个程序分为三个步骤:  
                输入数据  --> 计算 ---> 写回文件
            
            缺陷:  
                CPU利用率很低
        
        
    (2)并发执行   
        把一个指令的执行过程,分为几个不同的步骤:   
            取指  --> 执行  -->  写回 
        不同的步骤,由不同的硬件完成。
            
        这样的话,就可以多个程序同时执行。
        
        为了提高cpu的利用率,增加吞吐量。"并发执行"
        
    现代操作系统为了能让程序并发执行,特地引入"进程"的概念    


    
1.进程是什么东西?   


    进程是具有独立功能的程序关于某个数据集合上的一次运行活动。(跑起来的程序)
    test.c   --> 源程序  
        int main()
        {
            int  a, b; 
            int sum;  
            scanf("%d%d",&a,&b);
            
            sum = a + b;
        
            printf("sum = %d\n",sum);
            
            return 0;
        }
        
        gcc test.c -o test =>test 可执行程序  
        
        ./test 

2.进程与程序区别  


    (1)程序是静态概念(是指令的有序集合,"程序文件");
        进程是动态概念(动态产生,动态消亡);
        
    (2)进程是一个程序的一次执行活动,
        一个程序可以对应多个进程
        
    (3)进程是一个独立的活动单位;
        进程是竞争系统资源的基本单位   
        
    例子:    
        进程与程序的区别,就好比"炒菜活动与菜谱"的区别 
    
    OS为什么要引入进程呢?  
        就是为了能让程序并发执行(同一时段有多个程序在运行)
        进程是如何做到让多个程序并发执行的呢?  
        
        程序的并发,实际就是进程的并发。
        进程如何同时运行呢? 进程如何并发的呢? 
        


3.进程状态    

(需要掌握一定的计算机组成原理的知识,PC寄存器存储下一条执行的指令...)

进程在其执行过程中会经历不同的状态。根据经典的进程状态模型,常见的进程状态包括:

1. 创建(Create):当进程被创建但尚未开始执行时,处于创建状态。此时操作系统正在为进程分配必要的资源,并初始化进程的上下文。

2. 就绪(Ready):就绪状态表示进程已准备好运行,但还未分配到 CPU 时间片。进程已经完成了初始化,并等待被调度器挑选为下一个要执行的进程。

3. 运行(Running):运行状态表示进程当前正在执行中。在单处理器系统中,每个时刻只有一个进程能够运行。在多处理器系统中,多个进程可以同时处于运行状态。

4. 阻塞(Blocked):当进程在执行过程中遇到某些阻塞事件(比如等待 I/O 完成、等待锁、等待信号量等)时,进程会进入阻塞状态,暂时停止执行。在这种状态下,进程不会被调度执行,直到等待的事件发生并解除阻塞。

5. 终止(Terminated):当进程的执行结束时,进程进入终止状态。系统会回收该进程所分配的资源,并向其父进程发送退出状态。

需要注意的是,不同的操作系统和调度算法可能会对进程状态模型进行细微的调整或扩展。

此外,还存在一些扩展的进程状态,如挂起(Suspended)、睡眠(Sleeping)等,用于描述一些特定的等待或暂停状态。这些状态在特定的操作系统环境下有特定的含义和用途。

进程状态的转换是由操作系统的调度器来控制的,根据调度算法和各个进程的状态和优先级决定进程的转换和执行顺序。

        
    进程的这些状态之间可以进行切换。

    "就绪队列: Ready Queue"
        所有处于"Ready"状态的进行,都在一个"后备队列"
        
        "调度程序":负责确定下一个进入"Running"状态的进程
        
    "调度策略":调度算法  
        分时系统:调度策略以"时间片轮转"为主要策略的系统  
            “事件片轮转”:分时,每个进程执行一段时间("时间片")
            
            如: 大部分桌面系统,如:linux,andriod,windows,  
                    macos,unix,...
            
        实时系统:调度策略以"实时策略"为主要策略的系统
            “实时策略”:每次调度都去优先级最高的那个进程执行,
                        直到这个进程执行完毕或它主动放弃CPU或其它
                        更高优先级的进程抢占. 
                        
            如:ucos,freeRTOS...
                “抢占”: 插队  
        
    程序的执行过程“进程”  
        程序的执行,分配资源, =》“进程”
        
    程序 = 数据 + 指令   
    
    进程要做的第一件事件,就是申请一块内存区域来存储程序
    的“数据”,不同的"数据"属性是不一样的,"分区域"
    来存储程序的数据 
    


4.linux进程地址空间布局   


    "分段":分不同的逻辑区域
    linux对进程的数据进行分段管理,不同的属性的数据,存储在
    不同的“内存段”中。不同的"内存段(内存区域)"的属性及管理方法
    不一样。
    
    
    .text
        主要存放代码。
        只读并且共享,这段内存在程序运行期间(进程存活期间),不会释放的。
        "代码段" 随进程持续性
    .data
        数据段。  
        主要存放程序的已经初始化的全局变量和已经初始化的static变量。
        可读可写,这段内存在进程运行期间,一直存在。随进程持续性。

    .bss  
        数据段。  
        主要存放程序的没有初始化的全局变量和没有初始化的static变量。
        可读可写,这段内存在进程运行期间,一直存在。随进程持续性。
        .bss段,在进程初始化时,(可能)全部初始化为0.

    .rodata 
        只读数据段。  
        主要存放程序中的只读数据(如:字符串常量)
        只读,这段内存在进程运行期间,一直存在。随进程持续性
        
    
    栈空间(stack)
        主要存放局部变量(非static的局部变量)
        可读可写。这段空间,会自动释放(代码块执行完了,代码块中的局部变量的空间
        就会被自动释放)。随代码块的持续性。
        
        返回一个局部变量的地址,是有问题的,就是这个原因。

    堆(heap)空间:动态内存空间   
        主要malloc/realloc/calloc 动态分配的空间。
        可读可写的,这段内存在进程运行期间,一旦分配,就
        会一直存在,直到你手动free 
        (编程时一般只会接触到堆栈)
        防止“内存泄露”/“垃圾内存”
        
        int main()
        {
            char *s = "12345";  
            //s存放在栈空间  
            //"12345" .rodata 
        }
         
        
        int a;  
        int b = 3;
        int main()
        {
        }
          // a存放在.bss  
          // b存放在.data  
        
        int main()
        {
            char str[] = "12345";
            //str存放在栈空空间
            //"12345" 栈空间 
        }        
        
        int main()
        {
            int *p = malloc(100);
            //p存放在栈空间
            //malloc的空间在堆
        }

5.linux下进程相关的API函数  


    (1)创建一个新进程   


     fork    
        
            fork用来创建一个新进程(child proccess),你要创建一个新进程,首先你得 
            知道一个进程里面包含什么东西?  
                
                系统数据 
                用户数据
                指令 
            fork一个新进程时,这个新进程的 数据 和 指令 来源于哪里呢?
                来源于它爸爸(父进程,调用fork的那个进程)
                
            fork这个函数在创建子进程时:  
                copy了父进程的数据和指令!!!
                父进程的变量,数据对象,
                标准IO缓冲区
                文件描述符
                ...
                copy完了后,父子进程就独立了。
                
            通过fork的不同的返回值,来区分到底是父进程返回,还是子进程返回。
        (注意:fork创建出来的子进程相当于复制了一个父进程,拷贝了父进程里面所有的数据和指令,复制完成之后,父子进程独立)
        
        头文件 
            #include <sys/types.h>
            #include <unistd.h>
        函数功能
            创建一个子进程
        函数原型
             pid_t fork(void);
        函数参数
            无
        函数返回值
            如果失败返回-1,同时errno被设置。
            如果成功:  
                父进程返回 子进程的pid( > 0) 
                子进程返回  0
                
            pid_t fork()
            {
                clone();  //克隆,一旦成功,就会有两个进程往下执行 
                            //父进程  //子进程  
                            
                if(父进程)
                {
                    return 子进程的pid( > 0)
                }                
                else if (子进程)
                {
                    return 0;
                }
            }    
            
        ------
        linux系统会为每一个进程,分配一个唯一的进程id(> 0 的整数),用类型pid_t
        来描述,而且还提供两个函数用于获取当前进程(自己)以及父进程的pid;
        
            头文件 
                #include <sys/types.h>
                #include <unistd.h>
            函数原型 
                pid_t getpid(void);  //用于获取自己的进程pid 
                pid_t getppid(void); //用于获取父进程的pid 


    (2)进程退出  


        进程退出有两种情况:  
        (2.1)自杀 (自己退出)
            a:main函数返回,进程退出
            b:在进程执行的任意,调用进程退出函数
                exit/_exit
                头文件 
                     #include <stdlib.h>
                函数功能 
                    让进程退出,正常退出,做一些清理工作(如:把缓冲区的内容,同步到文件中去)
                    
                函数原型
                    void exit(int status);
                函数参数
                    int status    //表示退出码,表示退出状态 
                                退出码的具体含义,由程序员来解释。    
                函数返回值 
                    无
                
                头文件  
                     #include <unistd.h>
                函数功能
                    _exit 坐火箭走的,让中止进程,来不及做清理工作
                函数原型 
                     void _exit(int status);
                函数参数 
                    int status    //表示退出码,表示退出状态 
                                退出码的具体含义,由程序员来解释。
                函数返回值 
                    无
        
            例子:  
                1.分析如下程序的输出结果 
                    int main()
                    {
                        printf("hello world");
                        _exit(-3);
                    }
                    终端没有任何输出
                    int main()
                    {
                        printf("hello world ");
                        exit(0);
                    }
                    终端输出hello world 
        
        
        
        (2.2)被操作系统干掉了
            比如我们的段错误之类的。

    (3)等待子进程退出 


        wait   
        waitpid 
        头文件  
            #include <sys/types.h>
            #include <sys/wait.h>
        函数功能
            等待子进程退出 
        函数原型 
            pid_t wait(int *wstatus);

            pid_t waitpid(pid_t pid, int *wstatus, int options);
            
        这两个函数用来等待某个(些)子进程的状态发生改变的,等待的状态
        发生改变有三种情况:   
            a.子进程退出(正常退出):main函数返回值/exit/_exit 
            b.子进程被信号中止 
            //c.子进程被信号唤醒(blocking -> ready)
            
        在子进程正常退出(a)情况,调用wait/waitpid可以释放子进程的资源
        假如没有调用wait/waitpid,那么子进程退出后,就会变成僵尸进程(zomble)
            一个进程退出,操作系统会释放他大部分的资源,但是有一部分
            必须留给他的父进程去释放。如果一个进程退出了,但是它父进程没有
            wait/waitpid,这个进程就会变成僵尸进程:已经死掉了 但是资源没有
            被完全释放掉。
            
        假如一个子进程的状态已经发生改变,那么调用wait/waitpid就会立即返回,    
        否则会阻塞调用进程直到某个子进程的状态发生改变或被信号中断。

        pid_t wait(int *wstatus); 用来等待任意一个子进程退出的状态    
        函数参数 
            int *wstatus  //指针。指向的空间,用来保存子进程的退出信息的
            (怎么死的,退出码等等)
            
            wstatus 用来保存退出的子进程的退出信息的,退出信息保存在一个整数。
            我们可以用如下宏来解析子进程的退出信息:  
                WIFEXITED(wstatus)
                    return  true 
                    假如该子进程是正常退出的(main返回/exit/_exit)
                    只有子进程正常退出,它才会有退出码!!!
                    
                    WEXITSTATUS(wstatus)
                        返回子进程的退出码,只有子进程正常退出 
                        这个宏才有意义,
                        把进程的退出码, unsigend char 来看待 
                    
                WIFSIGNALED(wstatus)
                    return true  
                    假如子进程是被信号干掉的
                    ...
        
        
    
    
            pid_t waitpid(pid_t pid, int *wstatus, int options);  
                pid_t pid   //指定要等待的进程或进程组
                            pid == -1,表示等待任意的子进程退出
                            pid == 0,表示等待与调用进程同组的任意子进程
                            "进程组" 
                                就是一组进程。每个进程必须会属于某一个进程组。
                                并且每个进程组,都会有一个组长进程,一般来说, 
                                创建这个进程组的进程为组长,进程组有一个组id,
                                这个组id,就是组长进程的pid,
                            pid < -1 表示等待组id等于 pid绝对值的那个组的任意子进程
                            
                            如:  
                                pid == -128  
                                等待进程组 128那个组内的任意的子进程 
                                
                            pid > 0,表示等待指定的子进程(其进程id为pid的那个进程)

                int *wstatus  //同上。  

                
                int options     //等待选项 
                             0:表示阻塞等待 
                             WNOHANG:非阻塞,假如没有子进程退出,则立即返回。
                
                wait(&wstatus)
                    <=> waitpid(-1,&wstatus,0);
                
            函数返回值 
            成功:返回退出的那个子进程的进程id   
            失败:返回-1,同时errno被设置。
            (父进程创建了子进程之后,子进程默认会继承父进程的进程组。所以他的孙子,孙孙子,都会在最开始创建它爸爸的组里。main函数的进程
            组由操作系统分配)
            
    fork一个子进程,一般来说,是让子进程去执行其它的任务      
        (不是说创建的子进程就必须要在父进程里面用wait等待,有时候父进程也要做自己的事情,你在子进程调用Exit退出时,只需要手动清理
        文件描述符,套接字,堆内存就极少情况下会出现僵尸进程。不用刻意在主进程里调用wait等待子进程的退出)


    (4)让一个进程去执行一个指定的程序文件


        exec函数族 主要作用是 让一个进程去执行一个指定的程序文件。
        或者这么理解:exec函数族的作用就是让一个指定的程序文件中的 
        数据和指令替换到 调用进程 的数据和指令
        
        exec函数族是让一个进程去指定另外一个程序文件。
        就是让另外一个程序文件的数据和指令,覆盖当前进程的数据和指令。  
        
        
        exec让一个进程去执行另外一个程序,那么:  
            你是不是要指定这个程序文件的名字? 
                一个子文件系统中的程序文件的名字(带路径)
            你可能还得指定程序运行的参数!!!
                在linux下程序的参数,都是字符串
                
                指定程序的参数有两种方式:  
                    l:list 
                        把程序运行的参数,一个一个地列举出来。
                        程序运行的第一个参数,是程序的名字(不带路径)
                        gcc sum.c -o sum 
                        
                        "sum","3","4",NULL

                    v:vector 向量,数组
                        把程序运行的参数,弄成一个char *数组  
                        char *arg[] = {"sum","3","4",NULL};
        头文件
            #include <unistd.h>
        函数功能
            让进程去执行参数指定的程序文件。
        函数原型
            int execl(const char *path, const char *arg, ...);
        函数参数 
            const char *path        //程序文件的文件名(带路径的)
            const char *arg, ...    //程序运行的参数,以列表的形式给 
                    如:
                        "sum","3","4",NULL

                        
        函数返回值:  
            失败: 返回-1,同时errno被设置。
            成功:就永远不会返回了!!!因为你的整个指令和数据段,
                    都被人家替换掉了,还怎么返回呢?
        

            execv与execl作用、功能、返回值都是一样的。 
            唯一不同的是,指定的程序文件的参数方式不一样。
            
        函数原型 
            int execv(const char *path, char *const argv[]); 
        函数参数  
            const char *path        //要执行的程序文件名(带路径)
            char *const argv[]        //指定程序运行的参数。程序运行的第一个参数
                                    是程序名,最后一个为NULL,表示参数结束了。
            
            系统中有一个环境变量 PATH
                环境变量:是整个系统环境内所有进程共享的变量。
                有很多的环境变量,其中一个环境变量叫  PATH 
                    PATH:=dir1:dir2:dir3 ...
                PATH的作用是,指定命令或程序的搜索路径,什么意思呢? 
                当你只指定了一个命令或程序的文件名,而没有指定路径时,
                那么系统首先会在dir1这个目录下去查找,如果找到,则执行,
                没有找到,则在dir2这个目录下查找,...全部找完没找到就会
                报错。
                
                意思是说,如果你的程序文件或命令已经在PATH指定的搜索目录下
                的时候,你指定文件时就没有必要指定路径了。
                
                
                p:path    
                    指定的程序文件在标准的搜索路径下面  
                    
                    execlp 
                    execvp 
                    
                int execlp(const char *file, const char *arg, ...);    
                    file:要执行的程序文件名(可以不带路径)
                    arg:...    
                int execvp(const char *file, char *const argv[]);                    
                    ...
        ----
            fork() 
                -->exec 
                    
            有一个一步到位的函数 

    (5)执行指定的程序


        头文件 
            #include <stdlib.h>
        函数功能
            system用来执行command指定的命令或程序
            system会等待命令或程序执行完成才返回
        函数原型
            int system(const char *command);    
        函数参数
            const char *command    //要指定的命令字符串的地址
        函数返回值 
            system函数对返回值的处理,设计三个阶段: 
                1.创建子进程等准备工作,如果失败,返回值-1;
                2.调用某个可执行程序,如果没有找到可执行程序或者可执行程序
                    未正常运行。原因值被写入到返回值的低8-15比特中。系统提供了宏;
                    WEXITSTATUS(返回值)。如果WEXITSTATUS(返回值)为真,则说明正常结束
                3.如果可执行程序正常执行结束,将可执行程序返回填到返回值的8-15比特位中。
                    系统提供了宏;WEXITSTATUS(返回值)
        综上所述  
            判断一个sytem函数调用可执行程序是否正常结束的方法应该是 
            如下3个条件同时成立: 
                (1) -1 != status
                (2)WEXITSTATUS(status)为真 
                (3)调用的可执行程序在正常结束后返回的那个返回值或者说是
                    退出码 == WEXITSTATUS(status)
                            
                            
            madplay xxx.mp3
            
            例子: 
                system("madplay xxx.mp3");
                or  
                char cmd[256] = {0}; 
                sprintf(cmd,"madplay %s",p->mp3name);
                system(cmd);           

            
    总结:  


        (1)进程的概念 
           进程与程序的区别 
           
        (2)进程的状态切换 
        
        (3)调度策略 
            分时系统 
            
            实时系统 
        
            抢占  
                "就绪队列"
                
        (4)fork实现原理  
            a.clone  
            b.独立了
            
        (5)exec* 函数族    

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

并发编程基础知识(一)[进程篇] 的相关文章

  • 如何修复“iptables:没有该名称的链/目标/匹配”?

    我在我的 Linux 嵌入式系统上构建并安装了 iptables 如果我列出所有规则 则一切正常 iptables list Chain INPUT policy ACCEPT target prot opt source destinat
  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • 修改linux下的路径

    虽然我认为我已经接近 Linux 专业人士 但显然我仍然是一个初学者 当我登录服务器时 我需要使用最新版本的R 统计软件 R 安装在 2 个地方 当我运行以下命令时 which R I get usr bin R 进而 R version
  • 使用 grep 查找包含所有搜索字符串的行

    我有一个文件 其中包含很多与此类似的行 id 2796 some model Profile message type MODEL SAVE fields account 14 address null modification times
  • 从 csv 文件中删除特定列,保持输出上的相同结构[重复]

    这个问题在这里已经有答案了 我想删除第 3 列并在输出文件中保留相同的结构 输入文件 12 10 10 10 10 1 12 23 1 45 6 7 11 2 33 45 1 2 1 2 34 5 6 I tried awk F 3 fil
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • Jenkins中找不到环境变量

    我想在詹金斯中设置很多变量 我试过把它们放进去 bashrc bash profile and profile of the jenkins用户 但 Jenkins 在构建发生时找不到它们 唯一有效的方法是将所有环境变量放入Jenkinsf
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 无法从 jenkins 作为后台进程运行 nohup 命令

    更新 根据下面的讨论 我编辑了我的答案以获得更准确的描述 我正在尝试从詹金斯运行 nohup 命令 完整的命令是 nohup java jar home jar server process 0 35 jar prod gt gt var
  • Linux 中的动态环境变量?

    Linux 中是否可以通过某种方式拥有动态环境变量 我有一个网络服务器 网站遵循以下布局 site qa production 我想要一个环境变量 例如 APPLICATION ENV 当我在 qa 目录中时设置为 qa 当我在生产目录中时
  • 如何在数组中存储包含双引号的命令参数?

    我有一个 Bash 脚本 它生成 存储和修改数组中的值 这些值稍后用作命令的参数 对于 MCVE 我想到了任意命令bash c echo 0 0 echo 1 1 这解释了我的问题 我将用两个参数调用我的命令 option1 without
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • nslookup 报告“无法解析 '(null)': 名称无法解析”,尽管它成功解析了 DNS 名称

    我在 ubuntu 上 并且正在运行 docker 默认桥接网络 我有 Zookeeper kafka 的容器化版本 以及我编写的与 kafka 对话的应用程序 I do a docker exec it
  • 添加要在给定命令中运行的 .env 变量

    我有一个 env 文件 其中包含如下变量 HELLO world SOMETHING nothing 前几天我发现了这个很棒的脚本 它将这些变量放入当前会话中 所以当我运行这样的东西时 cat env grep v xargs node t
  • 无法使用 wget 在 CentOS 机器上安装 oracle jdk

    我想在CentOS上安装oracle java jdk 8 我无法安装 java jdk 因为当我尝试使用命令安装 java jdk 时 root ADARSH PROD1 wget no cookies no check certific
  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • 在 Linux 上使用多处理时,TKinter 窗口不会出现

    我想生成另一个进程来异步显示错误消息 同时应用程序的其余部分继续 我正在使用multiprocessingPython 2 6 中的模块来创建进程 我试图用以下命令显示窗口TKinter 这段代码在Windows上运行良好 但在Linux上
  • jpegtran 优化而不更改文件名

    我需要优化一些图像 但不更改它们的名称 jpegtran copy none optimize image jpg gt image jpg 但是 这似乎创建了 0 的文件大小 当我对不同的文件名执行此操作时 大小仍然完全相同 怎么样 jp

随机推荐

  • Java 中的Lock锁对象(ReentrantLock/ReentrantReadWriteLock)详解

    目录 1 Lock Objects 详解 2 Java 中的 Lock Objects 的实现原理 3 ReentrantLock 详解 4 ReentrantReadWriteLock 详解 5 Lock锁的等待和唤醒 6 Lock 和
  • 代码的执行原理

    代码的执行原理 一 代码段 什么是代码段 一个script标签就是一个代码段 JS代码在执行时 是一个代码段一个代码段执行 二 代码执行的步骤 JS代码在执行时分两个阶段 1 预编译 2 代码执行 每一个阶段做的事情是不一样的 先了解一下定
  • UE5 Rokoko Studio Live(动捕实时链接)

    UE5 Rokoko动作捕捉实时 一 新建初始化项目 添加插件 打开UE5 1 1 新建 第三人称游戏 文件夹筛选找到模板自带的关卡 新建动画蓝图 gt 然后选择到UE的小白人骨骼 因为我们需要Rokoko的实时动捕 需要在项目里添加Rok
  • IDEA常用快捷键

    IDEA常用快捷键 快捷键 描述 Ctrl Shift R 全局搜索 替换 Ctrl Shift F 全局搜索 Ctrl F 局部搜索 Shift双击 搜索类 接口等 Ctrl 鼠标点击类名称 进入类的内部 Ctrl Alt O 清除不使用
  • 气候数据处理代码实现

    案例 根据站点降雨量日数据求月总降雨量 年总降雨量 月降雨天数 年降雨天数等 数据 部分数据如下 统计结果
  • 怎么理解KMP算法中的next数组(为甚有时候加一有时候不加一?)

    KMP算法怎么来的和找规律 以及对于BF算法他的主要区别就不再赘述我们 我们来说一下怎么用最快的速度加上已知规律找到给定字符串的next数组 C语言中和java中都适用 我们已经找到了部分规律 next数组中的值可能和已匹配部分字符串的前缀
  • 关于RabbitMQ的面试题

    关于RabbitMQ的面试题 整理了一下面试中问到rabbitmq消息队列时 面试官可能会问到的问题 面试题1 为什么使用rabbitmq 什么时候用 怎么用 一开始写项目 架构比较单一 使用的是单体结构 把所有的业务都堆积在一个项目里 随
  • [1220]hue数据导出

    1 执行要下载的sql语句 2 执行完成后 点击下面导出 3 选择所有 4 选择每个人对应的文件夹 没有自己名称的可以创建一个 5 选择导出 6 右面是导出执行时的界面 7 选择已经执行的文件 8 按照下面截图提示 就可以将文件下载到本地了
  • iOS上架报错:无法添加以供审核

    无法提交以供审核 要开始审核流程 必须提供以下项目 您必须为要添加的 app 提供版权信息 您在提交 app 审核时遇到的问题是因为需要提供版权信息 而您的 app 缺少相关的版权信息 以下是解决此问题的步骤 确认您是否拥有 app 的版权
  • kettle 关于数据库事务操作的解释说明

    事务与数据库 1 数据库连接只在执行作业或转换时使用 在作业里 每一个作业项都打开和关闭一个独立的数据库连接 转换也是如此 但是因为转换里的步骤是并行执行的 每个步骤都打开一个独立的数据库连接并开始一个事务 尽管这样在很多情况下会提高性能
  • Airbnb深度学习在搜索领域的探索总结

    今天的博客主要参考了Airbnb发表的paper Applying Deep Learning To Airbnb Search 这篇paper介绍了近2年Airbnb在搜索场景下所使用模型的演进路线 以及一些失败的总结和经验的总结 最难能
  • 常用的渗透测试工具之 SQLMap

    web安全攻防 第三章学习之SQLmap SQLMap介绍 SQLMap是自动化的SQL注入工具 主要功能是扫描 发现并利用URL的SQL注入漏洞 内置了很多绕过插件 SQLMap采用了五种独特的SQL注入技术 如下 1 基于布尔类型的盲注
  • maven deploy 遇到 “方法不会覆盖或实现超类型的方法” 不要慌

    思考问题 这个bug看的我莫名其妙 看名字也看不懂说的啥 在网上看到说什么把 Override去掉就行了什么 我就觉得很奇怪 跟这个能有什么关系呢 网上既然说是跟 Override有关 那么这应该是是跟我实现的接口有关 后来发现是我在接口中
  • 【星海随笔】Windows 下 安装 Eclipse IDE 编辑 C++ Code

    首先下载Eclips https download csdn net download weixin 41997073 86727250 安装后 然后点点点就可以了 但要记住自己安装的路径 安装后 先认识一下这个工具 File可以创建项目
  • sublime vue 语法高亮插件安装

    转自 http www cnblogs com cosnyang p 6290950 html 默认情况下 Vue js 的单文件组件 vue 在 sublime 编辑器中是不被识别的 若要想高亮显示 需要安装插件 Vue Syntax H
  • No such operator image::read_file问题解决

    在学习动手学深度学习这门课的时候 在13 6 节 标检测数据集这一章遇到了问题 读取数据的时候报错 No such operator image read file 网上有人说问题在于pytorch版本和torchvision版本不对应 可
  • weixin-js-sdk使用

    注意 以下内容自身的项目为uniapp编译生成微信小程序 小程序内嵌webview 一 微信初始化 安装微信sdk npm install weixin js sdk save 页面引入 import wx from weixin js s
  • 构建高性能数据库缓存之Redis(一)

    一 Redis概述 1 1 什么是redis Redis是一个开源的用ANSI C编写 支持网络 基于内存 亦可持久化的日志型 Key Value数据库 根据DB Engines com站点月度排行的数据显示 Reidis是最流行的键值对存
  • SpringBoot整合MinIO

    文章目录 1 问题背景 2 前言 3 步骤 3 1 引入依赖 3 2 连接MinIO服务端的必要参数 3 3 代码实现文件上传功能 3 4 验证 1 问题背景 前面搭建了MinIO容器 现在来研究SpringBoot整合MinIO 2 前言
  • 并发编程基础知识(一)[进程篇]

    目录 一 程序的执行方式 1 进程是什么东西 2 进程与程序区别 3 进程状态 4 linux进程地址空间布局 5 linux下进程相关的API函数 1 创建一个新进程 2 进程退出 3 等待子进程退出 4 让一个进程去执行一个指定的程序文