【Linux】进程创建、终止、等待、替换

news2024/9/20 6:40:14

进程控制

      • 进程创建
      • 进程终止
        • 终止进程的方法
      • 进程等待
      • 进程替换

进程创建

fork函数,它是从一个已存在的进程中创建一个新的进程。新的进程为子进程,而原进程为它的父进程。

fork函数的头文件为#include <unistd.h>
它的返回值为pid_t为无符号整型

在Linux中,pid_t是一个用于表示进程标识符(Process IDentifier)的数据类型。进程标识符是一个唯一标识一个正在运行的进程的整数值。
pid_t数据类型是一个有符号整数类型,它通常是signed int类型。它的值可以是正数、零或负数。
在Linux编程中,pid_t常用于获取当前进程的标识符、创建新进程和进程间通信等操作。每个进程都有一个唯一的进程标识符,它可以用来唯一标识和操作特定的进程。

进程 = 内核数据结构 + 进程代码和数据

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

当一个进程调用fork之后,就有两个二进制代码相同的进程。而且他们都运行到相同的地方。但每个进程都以及开始自己的旅程
当fork成功后,子进程中返回0,父进程返回子进程id,出错返回-1

 int main()
 {
   pid_t pid;
 
   printf("Before: pid is %d\n", getpid());
   if ( (pid=fork()) == -1 ) return 0;
   printf("After:pid is %d, fork return %d\n", getpid(), pid);
   sleep(1);
   return 0;
 }   

在这里插入图片描述
为什么子进程创建后,父子进程运行到那里,子进程就跟的运行到那里呢?
这是因为在我们的cpu中也有寄存器(EIP),每行代码加载到内存之后,都有对应的地址,都会记录在寄存器中,当我们程序发生意外终止时,再回来还可以通过cpu寄存器来重写找回地址接的运行。
每个进程都认为自己有一个寄存器,所以当fork之后,寄存器的起始位置就是fork之后的代码。

创建子进程,给子进程分配对应的内核结构,必须子进程自己独有,因为进程具有独立性。
因为子进程也要有自己的代码和数据,但是如果我们创建了子进程后,如果我们的子进程不立马运行并且不对父进程里的内容进行修改时,这两个进程是并用同一块数据空间的,当父进程或者子进程的数据进行修改后,就会发生写时拷贝
在这里插入图片描述

为社么要用写时拷贝呢
因为写时拷贝可以将自己进程彻底分离,完成了进程的独立性。
写时拷贝也是一种延时申请技术,可以提高整机内存的使用率。

进程终止

当进程终止的时候,系统会释放进程申请的相关内核数据机构和数据代码。

为什么main函数的return返回值为0

return返回的每个数字都有对应的退出错误原因,数字0为成功退出,接下来我们看一下main函数一共有多少种错误返回值。
进程退出码有利于我们快速的查找错误,解决错误

在这里插入图片描述

终止进程的方法

在谈如何终止进程的时候,我们要提取一个新的概念,那就是如何查找上一个进程的退出码为多少?
可以使用echo &?来访问上一个进程的退出码。
一般而言return对应的退出码。

在这里插入图片描述

return终止

main 函数里的终止才是真的进程终止

 1: process.c ? ?                                                                                                                                           ?? buffers 
  1 #include <unistd.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 
  6 int sum(int n)
  7 {
  8   int s = 0;
  9   int i = 0;
 10   for(i = 1;i<n;i++)
 11   {
 12     s+=i;
 13   }
 14   return s;
 15 }
 16 
 17 int main()
 18 {
 19   int res = sum(10);
 20   if(res != 5050)
 21   {
 22     //函数运行结果不正确,直接退出
 23     return 1;//返回错误信息                                                                                                                                         
 24   }
 25   return 0;
 26 }

在这里插入图片描述
exit终止进程

exit终止进程和return终止进程不一样的,exit终止进程的时候会调用清理函数和冲刷缓冲区,关闭流等,这个我们会在跟下边_exit的区别里头会有讲解。

在这里插入图片描述

 1: process.c  ⮀                                                                                                                                           ⮂⮂ buffers 
  1 #include <unistd.h>  
  2 #include <sys/types.h>                                                    
  3 #include <stdio.h>  
  4 #include <string.h>  
  5 #include <stdlib.h>  
  6 int sum(int n)  
  7 {  
  8   int s = 0;  
  9   int i = 0;  
 10   for(i = 1;i<n;i++)  
 11   {  
 12     s+=i;  
 13   }  
 14   exit(1);  
 15 }  
 16   
 17 int main()  
 18 {  
 19   int res = sum(10);  
 20   if(res != 5050)  
 21   {  
 22     //函数运行结果不正确,直接退出  
 23    exit(2) ;//返回错误信息                                                                                                                                        
 24   }                                                                                             
 25   return 0;                                                                                      
 26 }  

_exit终止

只要进程碰到_exit就会立马终止进程,不在进行任何操作。

 1: process.c ? ?                                                                                                                                           ?? buffers 
  1 #include <unistd.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 int sum(int n)
  7 {
  8   int s = 0;
  9   int i = 0;
 10   for(i = 1;i<n;i++)
 11   {
 12     s+=i;
 13   }
 14   _exit(3);
 15 }                                                                                                                                                                   
 16 
 17 int main()
 18 {
 19   int res = sum(10);
 20   if(res != 5050)
 21   {
 22     //函数运行结果不正确,直接退出
 23    _exit(2) ;//返回错误信息
 24   }
 25   return 0;
 26 }

在这里插入图片描述
exit 和 _exit 的区别

   int main()
   {
     printf("hello");
    sleep(3);
    exit(13);                                                                                                                                                        
  }

在这里插入图片描述

   int main()
   {
     printf("hello");
    sleep(3);
    _exit(13);                                                                                                                                                        
  }

在这里插入图片描述

我们从案例上可以看出,当exit退出终止进程的时候,会冲刷缓冲区,但是_exit就不会

在这里插入图片描述

进程等待

为什么要进行进程等待呢?
当子进程在父进程之前退出时,我们的子进程就会变为僵尸进程,这是我们就要运用等待来回收子进程。
等待也可以让父进程回收子进程的退出码,了解子进程的执行情况

wait阻塞式等待

当子进程全部运行终止后,才会再次运行父进程wait后半部分内容。并且子进程也会被回收,不在是僵尸进程。
成功后返回等待子进程的pid,失败返回-1

在这里插入图片描述

 1 #include <unistd.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <sys/wait.h>
  7 int main()
  8 {
  9   pid_t id = fork();
 10   if(id < 0)
 11   {
 12     perror("fork");
 13     exit(1);
 14   }
 15   else if(id == 0)
 16   {
 17     //子进程
 18     int cnt = 5;
 19     while(cnt)
 20     {
 21       printf("cnt: %d, 我是子进程, pid: %d, ppid : %d\n", cnt, getpid(), getppid());
 22       sleep(1);
 23       cnt--;
 24     }
 25     exit(0);                            
 26   }                    
 27   else
 28   {                                                                
 29     //父进程                                                     
 30     printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());
 		sleep(7);                                                                                                 
 31     pid_t ret = wait(NULL);//阻塞式等待
 32     if(ret > 0)                                          
 33     {                                         
 34       printf("等待子进程成功,ret : %d\n",ret);                                                                                 
 35     }                 
 36     while(1)
 37     {
 38       printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());
 39       sleep(1);
 40     }
 4142   }
 43 }

进程查找方式:while :; do ps ajx | head -1 && ps ajx | grep process | grep -v grep;sleep 1;echo "***************************************";done 在这里插入图片描述

waitpid阻塞等待

pid:
pid = -1,等待任一个子进程,与wait等效。
pid > 0,等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出
WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程退出码
status并不是按照整数整体使用的,而是按照比特位的方式,将32个
比特位进行划分,我们只学习低16位
options:
WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。
0:一直处于阻塞状态,直到子进程终止。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

 1 #include <unistd.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <sys/wait.h>
  7 int main()
  8 {
  9   pid_t id = fork();
 10   if(id < 0)
 11   {
 12     perror("fork");
 13     exit(1);
 14   }
 15   else if(id == 0)
 16   {
 17     //子进程
 18     int cnt = 5;
 19     while(cnt)
 20     {
 21       printf("cnt: %d, 我是子进程, pid: %d, ppid : %d\n", cnt, getpid(), getppid());
 22       sleep(1);
 23       cnt--;
 24     }                                                 
 25     exit(12);     
 26   }                                                    
 27   else               
 28   {                       
 29     //父进程                            
 30     printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());                                                                                                 
 31    sleep(7);
 32    int status = 0;
 33                                                                  
 34    // pid_t ret = wait(NULL);//阻塞式等待                 
 35    pid_t ret = waitpid(id,&status,0);
 36    if(ret > 0)
 37     {
 38       // 0x7F -> 0000.000 111 1111
 39       printf("等待子进程成功, ret: %d, 子进程收到的信号编号: %d,子进程退出码: %d\n",\
 40                     ret, status & 0x7F ,(status >> 8)&0xFF); //0xff --> 0000...000 1111 1111
 41     }
 42     while(1)
 43     {
 44       printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());
 45       sleep(1);
 46     }
 47     
 48   }
 49 }
 50 

在这里插入图片描述

在这里插入图片描述

进行非阻塞测试
在这里插入图片描述

 1 #include <unistd.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <sys/wait.h>
  7 int main()
  8 {
  9   pid_t id = fork();
 10   if(id < 0)
 11   {
 12     perror("fork");
 13     exit(1);
 14   }
 15   else if(id == 0)
 16   {
 17     //子进程
 18     int cnt = 5;
 19     while(cnt)
 20     {
 21       printf("cnt: %d, 我是子进程, pid: %d, ppid : %d\n", cnt, getpid(), getppid());
 22       sleep(1);
 23       cnt--;
 24     }
 25     exit(12);
 26   }
 27   else 
 28   {
 29     //父进程
 30     printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());                                                                                                 
 31    int Exit = 0;
 32    while(!Exit)
 33    {
 34 
 35    int status = 0;
36 
 37    // pid_t ret = wait(NULL);//阻塞式等待
 38    pid_t ret = waitpid(-1,&status,WNOHANG);
 39                                                                                                                                                                     
 40    if(ret > 0)
 41     {
 42       if(WIFEXITED(status))
 43       {
 44         // 0x7F -> 0000.000 111 1111
 45            printf("等待子进程成功, ret: %d, 子进程收到的信号编号: %d,子进程退出码: %d\n",
 46                     ret, status & 0x7F ,WEXITSTATUS(status)); //0xff --> 0000...000 1111 1111
 47           Exit = 1;
 48       }
 49     }
 50    else if(ret == 0)
 51    {
 52       printf("子进程还在运行中,暂时还没有退出,父进程可以在等一等, 处理一下其他事情??\n");
 53       printf("这里还可以执行其他命令\n");
 54       sleep(1);
 55    }
 56    else{
 57      //等待失败
 58      printf("wait失败!\n");
 59      Exit = 1;
 60    }
 61    }
 62     while(1)
 63     {
 64       printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());
 65       sleep(1);
 66     }
 67     
 68   }
 69 }

wait 和 waitpid

wait 和 waitpid可以拿到子进程的退出信息,那么为什么要用wait 和 waitpid函数呢?
这是因为进程之间具有写时拷贝功能,进程是具有独立性的,所以就需要用wait 和 waitpid函数来读取子进程的信息
那么wait 和 waitpid是凭什么能拿到子进程的信息呢?它们本来就是都是独立的,怎么可能呢?
这是因为wait 和 waitpid是读取子进程的task_struct结构的,当子进程位为僵尸进程的时候,子进程至少要保留进程的PCB信息,task_struct里面保留了任何进程退出时的退出结果信息
又因为wait 和 waitpid为系统调用,所以他们完成是有这个权力的。

进程替换

是什么?
如果我们创建新的子进程后,子进程想要执行一个全新的,这是我们就需要进行进程替换。
进程替换是通过特定的接口,加载磁盘上的一个权限程序(代码和数据),加载到调用进程的地址空间中,并和当前进程的页表重新建立映射。
怎么操作?

  1. 不创建子进程
  2. 创建子进程

#include <unistd.h>`
int execl(const char *path, const char *arg, …);
int execlp(const char *file, const char *arg, …);
int execle(const char *path, const char *arg, …,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

exec 后边的字母分别代表

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

在这里插入图片描述

创建子进程进行替换
1. 不创建子进程

int execl(const char *path, const char *arg, …);
在这里插入图片描述

  1 #include <unistd.h>
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <sys/wait.h>
  7 
  8 int main()
  9 {
 10   printf("当前进程开始\n");
 11   execl("/usr/bin/ls", "ls", "--color=auto","-l", NULL);
 12     exit(1);                                                                                                                                  
 13   printf("当前进程结束\n");
 14   return 0;
 15 }

在这里插入图片描述

替换成功后,后边的代码为什么不执行?
这是因为execl成功替换后,会将当前进程的所有代码和数据都进行替换。包括已经执行和未执行的。
所以一旦替换成功后续所有代码全部不会执行。
在这里插入图片描述

2. 创建子进程

当我们进程替换的时候,为什么要创建子进程呢?

  1. 为了不影响父进程,因为替换的时候,是代码和数据全部替换的,所以我们选择创建子进程,在子进程进行替换。此时父子进程和子进程的代码和数据就彻底分开了,虽然以亲并不冲突
  2. 我们想让父进程聚焦在读取数据,解析数据,指派进程执行代码的功能。

int execl(const char *path, const char *arg, …);
在这里插入图片描述
在这里插入图片描述

int execlp(const char *file, const char *arg, …)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
int execv(const char *path, char *const argv[])
在这里插入图片描述

int execvp(const char *file, char *const argv[])
在这里插入图片描述
int execle(const char *path, const char *arg, …,char *const envp[])
在这里插入图片描述

	exec.c
    1 #include <stdio.h>
    2 #include <unistd.h>
    3 #include <wait.h>
    4 #include <stdlib.h>
    5 
    6 #define NUM 16
    7 int main()
    8 {
    9   const char* myfile = "./mycmd";
   10   
   11   pid_t id = fork();
   12   if(id == 0)
   13   {
   14     //子进程
   15    printf("子进程开始运行,pid:%d\n",getpid());
   16    sleep(2);
   17    char* const _env[NUM]{
   18      (char*)"MY_105_VAL=888777666555",
   19     NULL
   20    };
   21    
W> 22    char* const  _argv[NUM]{
   23     (char*)"ls",
   24     (char*)"-a",
   25     (char*)"-l",
   26     (char*)"-i",
   27     NULL
   28    };
   29    execle(myfile,"mycmd","-a",NULL,_env);
   30    // execvp("ls",_argv);
   31    //execv("/usr/bin/ls",_argv);//和下面的execl只有传参方式的区别
   32    //execlp("bash","bash","test.sh",NULL); 
   33    //execlp("python", "python", "test.py", NULL);                                                                                           
   34    //execlp("ls","ls","-a","-l",NULL);
   35   // execl(myfile, "mycmd", "-b", NULL);
   36   // execl("/usr/bin/ls","ls","-a","-l",NULL);
   37    //如果替换失败就会走下面的程序
   38    exit(-1);
   39   }
   40   else 
   41   {
   42     //父进程
   43     printf("父进程开始运行,pid:%d\n",getpid());
   44     int status = 0;
   45     pid_t id = waitpid(-1,&status,0);
   46     //阻塞等待, 一定是子进程先运行完毕,然后父进程获取之后,才退出!
   47     if(id > 0)
   48     {
   49       printf("wait success,exit code: %d\n",WEXITSTATUS(status));
   50     }
   51   }
   52   return 0;
   53 }

 mycmd.c                                                                                                                    
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 int main(int argc,char *argv[])
  5 {
  6   if(argc != 2)
  7   {
  8     printf("can not execute!\n");
  9     exit(1);
 10   }
 11   printf("获取环境变量: MY_105_VAL: %s\n", getenv("MY_105_VAL"));
 12                                                                                                                                               
 13   if(strcmp(argv[1],"-a") == 0)
 14   {
 15     printf("hello a!\n");
 16   }
 17   else if(strcmp(argv[1],"-b") == 0)
 18   {
 19     printf("hello b!\n");
 20   }
 21   else
 22   {
 23     printf("default!\n");
 24   }
 25   return 0;
 26 }

test.py                                                                                                                    
  1 #! /usr/bin/python3.6                                                           
  2                                                                                 
  3 print("hello python");                                                          
  4 print("hello python");                                                          
  5 print("hello python");                                                          
  6 print("hello python");                                                          
  7 print("hello python");                                                          
  8 print("hello python");                                                          
  9 print("hello python");                                                          
 10 print("hello python");                                                          
 11 print("hello python");                                                          
 12 print("hello python");    
test.py                                                                                                                    
  1 #! /usr/bin/python3.6                                                           
  2                                                                                 
  3 print("hello python");                                                          
  4 print("hello python");                                                          
  5 print("hello python");                                                          
  6 print("hello python");                                                          
  7 print("hello python");                                                          
  8 print("hello python");                                                          
  9 print("hello python");                                                          
 10 print("hello python");                                                          
 11 print("hello python");                                                          
 12 print("hello python");    

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

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

相关文章

Responder与evil-winRM配合远程登录Windows

0x01.evil-winRM 0x01.1概述 在使用和介绍Responder之前&#xff0c;先来了解一下evil-winRM: evil-winrm是Windows远程管理(WinRM) Shell的终极版本。 Windows远程管理是WS 管理协议的 Microsoft 实施&#xff0c;该协议是基于标准 SOAP、不受防火墙影响的协议&#xff0c…

基于JavaWeb的ssm家居商城系统的设计与实现

基于JavaWeb的ssm家居商城系统的设计与实现035 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高…

知了汇智“2023年暑期双师型师资培训班”火热进行中

为贯彻落实中共中央、国务院印发《关于全面深化新时代教师队伍建设改革的意见》、国务院办公厅印发《关于深化产教融合的若干见》、教育部办公厅发布《关于做好职业教育“双师型”教师认定工作的通知》等文件精神&#xff0c;助力“双师型”教师联合培养&#xff0c;提升信息技…

爬虫逆向实战(七)--猿人学第十六题

一、数据接口分析 主页地址&#xff1a;猿人学第十六题 1、抓包 通过抓包可以发现数据接口是api/match/16 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以看出m是加密参数 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 无cook…

谷歌浏览器安装不上【搬代码】

winR 输入regedit 计算机\HKEY_CURRENT_USER\SOFTWARE\Google 然后重新安装谷歌

Linux驱动入门(6.2)按键驱动和LED驱动 --- 将逻辑电平与物理电平分离

前言 &#xff08;1&#xff09;在学习完Linux驱动入门&#xff08;6&#xff09;LED驱动—设备树之后&#xff0c;我们发现一个问题&#xff0c;设备树明明的gpios信息明明有三个元素gpios <&gpio5 3 GPIO_ACTIVE_LOW>; &gpio5 3 用来确定控制那个引脚&#xf…

vue,element。监听快捷键粘贴图片,添加到el-upload的列表。

在①中&#xff0c;粘贴图片&#xff0c;图片能够自动添加到底下el-upload组件的文件列表②。 // 对应① <el-card><el-tooltip content"粘贴图片至此" placement"top"><input readonly class"pasteImg" paste.prevent"hand…

GitHub Actions自动化部署+定时百度链接推送

前言 最近用VuePress搭建了一个静态网站&#xff0c;由于是纯静态的东西&#xff0c;每次修改完文章都要重新打包上传很是麻烦。虽然vuepress-theme-vdoing主题作者提供了GitHub Actions自动化部署的教程文章&#xff0c;但是过于简陋且是19年发布的。。 1. 创建一个GitHub仓…

从 1 杯咖啡到 1 首歌的时间,炎凰数据如何实现 Pipeline 执行提速 6 倍?

目录 痛点&#xff1a;工具链复杂、功能少、网不好&#xff0c;太 EMO&#xff01; 解法&#xff1a;All in one&#xff0c;一个平台串联需求→开发→发布 代码、CI/CD 一站式服务 需求、Story、Bug 一站式管理 关联代码 案例&#xff1a;3 个具体使用场景见真章 1. 灵…

MYSQL完全卸载、安装与账号创建、权限控制

一、卸载mysql CentOS 卸载 MySQL 1. 查看安装情况 使用以下命令查看当前安装mysql情况&#xff0c;查找以前是否装有mysql rpm -qa|grep -i mysql这里显示我安装的 MySQL 服务有有&#xff1a; 2. 停止 mysql 服务、删除之前安装的 mysql 删除命令&#xff1a;rpm -e –n…

聚焦纺织行业断线检测,AI机器视觉助力小场景的大未来

随着人工智能技术的发展&#xff0c;机器视觉以其快速、准确、高效的信息采集和处理优势&#xff0c;逐渐成为制造企业现代化升级不可缺少的技术之一&#xff0c;持续赋能相关传统劳动密集型产业的自动化与智能化转型。 传统劳动密集型产业对于人工依赖程度高&#xff0c;供应…

【IDEA报错:Cause: java.sql.SQLSyntaxErrorException: ORA-00942: 表或视图不存在】

报错内容如下&#xff1a; 2023-08-17 11:17:16.274 ERROR [egrant-biz,e44d96001eb5f212,e44d96001eb5f212,true] 29700 --- [ XNIO-1 task-2] c.i.c.l.c.RestExceptionController : 服务器异常org.springframework.jdbc.BadSqlGrammarException: ### Error queryin…

【计组】校验码(奇偶校验码、海明校验码、CRC)

前言 1、小提示&#xff1a;本篇博文是参考王道&#xff0c;在复习 ASCII 码的基础上&#xff0c;总结校验码的相关学习知识点&#xff0c;并在最后搭配习题&#xff08;含408真题&#xff09;进行巩固练习。&#xff08;对重点内容进行划线、标色&#xff09; 2、适用人群&…

前端笔试+面试分享

以下是个人线下面试遇到的真实的题&#xff0c;仅供参考和学习 1. css 选择符有哪些&#xff1f;哪些属性可以继承&#xff1f;优先级算法加何计算&#xff1f; CSS选择符有很多种&#xff0c;例如类型选择器、类选择器、ID选择器、属性选择器、伪类选择器、伪元素选择器等。 …

linux tomcat server.xml 项目访问路径变更不生效

如果想改成默认的127.0.0.1:8080 访问项目 先确定更改的作用文件 server.xml 的 host:appBase 标签 默认找到appBase webapps 下的war包&#xff0c;并解压&#xff0c;解压后的appname为访问路径 也就变成了 127.0.0.1:8080/appname host:Context:path 标签 appBase的 优先…

深度学习技巧应用25-深度学习在的常见问题与使用技巧,让大家更容易理解深度学习,通过面试

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下深度学习技巧应用25-深度学习在的常见问题与使用技巧&#xff0c;让大家更容易理解深度学习。在面对AI领域公司面试的过程中&#xff0c;往往面试官会针对AI领域或者算法实践进行提问&#xff0c;这些问题可能大家知…

laravel-admin之 解决上传图片不显示 $form->image(‘image‘); 及 $grid->column(‘image‘);

参考 https://blog.csdn.net/u013164285/article/details/106017464 $grid->column(‘image’)->image(‘http://wuyan.cn’, 100, 100); // //设置服务器和宽高 图片上传的域名 上传的图片不显示 在 这里设置了图片的上传路径 在这里设置 域名 就可以回显图片

如何用思维导图+Markdown提升工作效率?

在日常的工作中&#xff0c;我们常常需要记录一些信息、重要的事情或者一些重要的想法&#xff0c;Markdown就是一种非常好用的记录工具。搭配思维导图可以提高我们的记录效率&#xff0c;让我们的记录更加结构化。 为什么使用思维导图&#xff1f; 思维导图可以帮助我们整理…

你敢信?代码小白30min就能搭建一套酷炫级的驾驶舱!

大量研究结果表明&#xff0c;人类通过图像获取信息的速度比通过阅读文字获取信息的速度要快很多。 近几年&#xff0c;数据可视化在企业中越发“流行”&#xff0c;将数字以可视化的形式展示&#xff0c;不仅清晰明了地展现企业真正的实力&#xff0c;也能让管理者快速了解细节…

问道管理:股票打板风险大吗?怎么降低打板风险?

在股票市场上&#xff0c;一些出资者喜爱低吸&#xff0c;一些喜爱打板&#xff0c;那么&#xff0c;股票打板危险大吗&#xff1f;怎么下降打板危险&#xff1f;下面问道管理为大家准备了相关内容&#xff0c;以供参阅。 股票打板通常是指在个股涨停时买入&#xff0c;这种买入…