5、进程管理

进程的概念(详细)

为什么要有进程

  • 从理论角度看,是对正在运行的程序过程的抽象;
  • 从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序。

什么是进程

  • 狭义定义:进程就是一段程序的执行过程。
  • 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

进程的特征

  • 动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。

  • 并发性:任何进程都可以同其他进程一起并发执行

  • 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;

  • 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推 进

  • 结构特征:进程由程序、数据和进程控制块三部分组成;

    多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果; 但是执行过程中,程序不能发生改变。

Linux的进程结构

  • Linux进程结构:可由三部分组成:代码段、数据段、堆栈段。也就是程序、数据、进程控制块PCB(Process Control Block)组成。进程控制块是进程存在的惟一标识,系统通过PCB的存在而感知进程的存在。
  • 系统通过PCB对进程进行管理和调度。PCB包括创建进程、执行程序、退出进程以及改变进程的优先级等。而进程中的PCB用一个名为task_struct的结构体来表示,定义在include/linux/sched.h中,每当创建一新进程时,便在内存中申请一个空的task_struct结构,填入所需信息,同时,指向该结构的指针也被加入到task数组中,所有进程控制块都存储在task[]数组中。

进程的三种状态

  • 就绪状态:进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列。

  • 运行状态:进程占用处理器资源;处于此状态的进程的数目小于等于处理器的数目。在没有其他进程可以 执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。

    Linux进程在运行状态的四种状态

    1. R-run。正在运行

    2. T-stop。暂停运行

    3. S-sleep。睡眠

    4. Z-zombie。僵尸(或者叫将死)

      僵尸状态是一个特殊的状态。当前子程序退出,且父进程没有读取子进程退出的状态时,子程序就会进入僵尸状态,直到读取到子程序退出的信息了才会释放

  • 阻塞状态:由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生 前即使把处理机分配给该进程,也无法运行。

Linux进程的生命周期

  1. 创建阶段:系统进程通过调用fork()函数创建新的进程
  2. 就绪阶段:进程准备完成,等待被调用
  3. 运行阶段:进程被调度器选中并执行
    • 其中可能出现阻塞、僵尸状态
  4. 终止阶段:进程运行完毕

进程和程序的区别

  • 程序是指令和数据的有序集合,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个 动态的概念。
  • 程序可以作为一种软件资料长期存在,而进程是有一定生命期的。程序是永久的,进程是暂时的。
  • 进程是由进程控制块、程序段、数据段三部分组成;
  • 进程具有创建其他进程的功能,而程序没有。
  • 同一程序同时运行于若干个数据集合上,它将属于若干个不同的进程,也就是说同一程序可以对应多个进 程。
  • 在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单元都是进程。

进程控制

  • 创建进程

    • 引起创建进程的事件:

      1. 用户登录
      2. 作业调度
      3. 提供服务
      4. 应用请求
    • 进程的创建过程

      一旦操作系统发现了要求创建新进程的事件后,便调用进程创建原语Creat()按下述步骤创建一个新 进程。

      1. 申请空白PCB。为新进程申请获得唯一的数字标识符,并从PCB集合中索取一个空白PCB。

      2. 为新进程分配资源。

      3. 初始化进程控制块。PCB的初始化包括:

        ①初始化标识信息,将系统分配的标识符和父进程标识符,填入新的PCB中。

        ②初始化处理机状态信息,使程序计数器指向程序的入口地址,使栈指针指向栈顶。

        ③初始化处理机控制信息,将进程的状态设置为就绪状态或静止就绪状态,对于优先级,通常 是将它设置为最低优先级,除非用户以显式的方式提出高优先级要求。

      4. 将新进程插入就绪队列,如果进程就绪队列能够接纳新进程,便将新进程插入到就绪队列中

  • 进程终止

    • 引起进程终止的事件

      1. 正常结束
      2. 异常结束
      3. 外界干预
    • 进程的终止过程

      如果系统发生了上述要求终止进程的某事件后,OS便调用进程终止原语,按下述过程去终止指定的进 程。

      1. 根据被终止进程的标识符,从PCB集合中检索出该进程的PCB,从中读出该进程状态。

      2. 若被终止进程正处于执行状态,应立即终止该进程的执行,并置调度标志为真。用于指示该进程 被终止后应重新进行调度。

      3. 若该进程还有子孙进程,还应将其所有子孙进程予以终止,以防他们成为不可控的进程。

      4. 将被终止的进程所拥有的全部资源,或者归还给其父进程,或者归还给系统。

      5. 将被终止进程(它的PCB)从所在队列(或链表)中移出,等待其它程序来搜集信息。

  • 阻塞唤醒

    1. 引起进程阻塞和唤醒的事件

      1. 请求系统服务
      2. 启动某种操作
      3. 新数据尚未到达
      4. 无新工作可做
    2. 进程阻塞过程

      正在执行的进程,当发现上述某事件后,由于无法继续执行,于是进程便通过调用阻塞原语block把自 己阻塞。可见,进程的阻塞是进程自身的一种主动行为。进入block过程后,由于此时该进程还处于执 行状态,所以应先立即停止执行,把进程控制块中的现行状态由执行改为阻塞,并将PCB插入阻塞队 列。如果系统中设置了因不同事件而阻塞的多个阻塞队列,则应将本进程插入到具有相同事件的阻塞 (等待)队列。最后,转调度程序进行重新调度,将处理机分配给另一就绪进程,并进行切换,亦即, 保留被阻塞进程的处理机状态(在PCB中),再按新进程的PCB中的处理机状态设置CPU环境。

    3. 进程唤醒过程

      当被阻塞的进程所期待的事件出现时,如I/O完成或者其所期待的数据已经到达,则由有关进程(比如, 用完并释放了该I/O设备的进程)调用唤醒原语wakeup(),将等待该事件的进程唤醒。唤醒原语执行 的过程是:首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就 绪,然后再将该PCB插入到就绪队列中。

查看进程状态

ps:显示静态的进程状态

单词process的缩写,中文译为“进程”,其功能是显示当前系统的进程状态。

使用ps命令可以查看到进程的所有信息,例如进程的号码、发起者、系统资源(处理器与内存)使用占比、运行状态等。ps命令可帮助我们及时发现哪些进程出现“僵死”或“不可中断”等异常情‍况。

ps命令经常会与kill命令搭配使用,以中断和删除不必要的服务进程,避免服务器的资源浪费。

语法格式:ps 参数

注意:可以结合管道操作符来过滤出我们想要的信息

常用参数

参数 描述
-a 显示所有进程信息
-c 不显示程序路径
-d 不显示阶段作业程序
-e 显示环境变量信息
-f 用ASCII字符显示树状结构
-g 显示所有程序及其所属组的程序
-h 不显示标题列信息
-H 使用树状结构展示程序间的相互关系
-j 使用工作控制格式显示程序状态
-l 使用详细格式显示程序状态
-p 指定程序识别码并显示该程序的状态
-r 仅显示终端主机正在执行中的程序
-s 使用程序信号格式显示程序状态
-S 显示包括已中断的子程序的状态
-t 显示属于指定终端主机的程序状态
-T 显示当前终端主机下的所有程序
-u 使用用户为主的格式来显示程序状态
-U 显示属于指定用户的程序状态
-v 使用虚拟内存的格式显示程序状态
-w 使用宽阔的格式显示程序状态
-x 不区分终端主机
-X 使用旧式登录格式显示程序状态
-o 自定义显示的列
--cols 设置每列的最大字符数
--headers 重复显示标题列
--help 显示帮助信息
--info 显示排错信息
--lines 设置显示画面的列数
--version 显示版本信息

使用示例

  • 显示系统中的全部进程的详细信息,并使用用户为主的格式显示(省略了符号 “-”)

    [root@localhost rootdir]# ps aux
    USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root          2  0.0  0.0      0     0 ?        S    426   0:00 [kthreadd]
    root          4  0.0  0.0      0     0 ?        S<   426   0:00 [kworker/0:0H]
    root          6  0.0  0.0      0     0 ?        S    426   0:00 [ksoftirqd/0]
    
  • 结合重定向,将当前进程信息保留备份到指定文件:file

    [root@localhost rootdir]# ps aux > file
    
  • 结合管道操作符,将含有passwd字符的进程过滤出来

    [root@localhost rootdir]# ps aux | grep passwd
    root      32598  0.0  0.0 112824   980 pts/0    S+   04:04   0:00 grep --color=auto passwd
    
  • ps -aux输出的表格,按照表格的第3列数字大小进行降序排序

    [root@localhost rootdir]# ps -aux | sort -rnk 3
    
  • 查看进程的父进程ID

    [root@localhost rootdir]# ps -ef
    
  • 只想显示PID、%CPU、COMMAND这三列的信息。注意:o必须在最后面

    [root@localhost rootdir]# ps -axo pid,%cpu,command
       PID %CPU COMMAND
         2  0.0 [kthreadd]
         4  0.0 [kworker/0:0H]
         6  0.0 [ksoftirqd/0]
         7  0.0 [migration/0]
         8  0.0 [rcu_bh]
    	 ...		// 后面还有很多,就不全拿过来了
    

top:显示动态的进程状态

top命令的功能是实时显示系统运行状态,包含处理器、内存、服务、进程等重要资产信息。运维工程师们常常会把top命令比作“加强版的Windows任务管理器”,因为除了能看到常规的服务进程信息之外,还能够对处理器和内存的负载情况一目了然,实时感知系统全局的运行状态。top命令非常适合作为接手服务器后执行的第一条命令。

语法格式:top 参数 对象

注意:按q或Ctrl+c退出

常用参数

参数 描述
-a 按内存使用情况排序
-b 使用批处理模式,不进行交互式显示
-c 提供完整的路径及名称
-d 设置显示的更新速度
-h 显示帮助信息
-i 不显示任何闲置或僵死的行程
-M 显示内存单位
-n 设置显示的总次数,完成后自动退出
-p 仅显示指定进程ID
-s 使用安全模式,不允许交互式指令
-u 仅显示与指定用户ID
-v 使用线程模式
-w 设置显示的宽度

使用示例

  • 以默认格式显示系统运行信息

    [root@localhost rootdir]# top
    
  • 设置每5秒刷新一次

    [root@localhost rootdir]# top -d 5
    
  • 使用批处理模式

    [root@localhost rootdir]# top -b
    
  • 只看进程号:1、2的进程信息

    [root@localhost rootdir]# top -p 1,2
    

top的交互模式

top内可以进行交互

常用的交互

  • h:进入帮助
  • M:按内存的使用排序
  • P:按CPU的使用率排序
  • N:以PID的大小进行排序
  • 空格:按一下暂停刷新,在按一下恢复
  • <:向前
  • >:向后
  • z:换一种颜色显示
  • q:退出

进程状态中字段(表头)的含义

ps的字段

使用ps aux | head -1ps -ef | head -1获取

[root@localhost rootdir]# ps aux | head -1
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

[root@localhost rootdir]# ps -ef | head -1
UID         PID   PPID  C STIME TTY          TIME CMD
  • USER:运行进程的用户
  • PID:进程的ID
  • PPID:当前进程的父进程ID
  • %CPU:CPU占用率
  • %MEM:内存占用率
  • VSZ:占用的虚拟内存
  • RSS:占用的实际内存
  • TTY:进程运行的终端
  • STAT:进程的状态
  • START:进程启动的时间
  • TIME:进程占用CPU的总时间
  • COMMAND:进程文件,进程名
  • C:

top的字段

top显示的部分分为上下两个部分,红框的是上半部分,蓝框的是下半部分

  • 上半部分:显示性能

第四行是物理空间的占用率

第五行是虚拟内存的占用率

  • 下半部分:

    • PID、USER、%CPU、MEM在ps命令里面介绍过

    • PR:进程优先级

    • NI:nice值。负值表示高优先级

    • VIRT:进程使用的虚拟内存总量,单位:kb。VIRT=SWAP+RES

    • RES:进程使用的、未被换出来的物理内存大小,单位:kbRES=CODE+DATA

    • SHR:共享内存大小,单位:kb

    • S:进程状态

      D:不可中断的睡眠

      R:运行

      S:睡眠

      T:暂停

      Z:僵尸

使用信号控制进程

信号参数

使用命令kill -l查看

常用的前十五个信号:

  • 1)SIGHUP:用于断开进程与父进程的连接,这也可以用于重新启动进程,这对于内存泄漏的守护程序很有用。终端断线

    用途:当控制终端(通常是终端会话)结束或挂起时发送。常用于通知守护进程(daemon)重新读取配置文件。

  • 2)SIGINT: 该信号与按Ctrl+C相同,在某些系统上delete + break会向进程发送相同的信号,该进程被中断并停止,但是该进程自身可以忽略此信号。

    用途:当用户按下中断键(通常是Ctrl+C)时发送。用于中断前台进程。

  • 3)SIGQUIT: 这类似于SIGINT,但由于QUIT字符通常是由Ctrl+\来控制,进程在收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。 退出(同 Ctrl + \)

    用途:与SIGINT类似,但会产生核心转储(core dump)。常用于调试。

  • 4)SIGILL: 当一个进程执行一个错误的、禁止的或未知的功能时,系统向该进程发送SIGILL信号,这是代表非法操作的信号。

    用途:当进程执行了非法或未知的指令时发送。用于指示进程中的指令错误。

  • 5)SIGTRAP: 此信号用于调试目的,当某个进程执行了某个操作或满足了调试器正在等待的条件时,此信号将被发送到该进程。

    用途:常用于调试器,当遇到断点(breakpoint)时暂停进程。

  • 6)SIGABRT: 该终止信号是中止信号,通常进程会在自身上发出此终止信号。

    用途:当程序调用abort()函数时发送。用于程序自我终止并可能产生核心转储。

  • 7)SIGBUS: 当一个进程被发送SIGBUS信号时,是因为该进程导致了一个总线错误,通常这些总线错误是由于进程试图使用假物理地址或进程的内存对齐设置不正确造成的。

    用途:模拟指令异常,较少使用。

  • 8)SIGFPE: 被零除的进程使用SIGFPE终止。

    用途:当发生浮点错误(如除以零)时发送。用于指示浮点运算中的错误。

  • 9)SIGKILL: SIGKILL这是一个强制终止信号,进程不能忽略它。当 SIGTERM 信号无效或需要立即终止进程时,可以使用此信号强制终止

    用途:强制终止进程。该信号不能被进程忽略或捕获,常用于强制结束无法响应的进程。

  • 10)SIGUSR1: 这表示用户定义的条件,用户可以通过在sigusr1.c中编程命令来设置此信号。

    用途:当进程访问了无效的内存地址或发生了其他总线错误时发送。

  • 11)SIGSEGV: 当应用程序有分段冲突时,这个信号被发送到进程。

    用途:当进程访问了无效的内存地址时发送,也称为段错误。

  • 12)SIGUSR2: 这表示用户定义的条件。

    用途:当进程执行了非法的系统调用时发送。

  • 13)SIGPIPE: 当进程尝试写入缺少与读取器连接的一端的管道时,此信号将发送到进程,读取器是在管道末端读取数据的过程。

    用途:当进程向没有读者的管道写数据时发送。通常用于指示管道问题。

  • 14)SIGALRM: 当实时或时钟计时器到期时,将发送SIGALRM。:通常用于实现定时器或超时功能。

    用途:定时器到期时发送。常用于实现定时器或超时功能。

  • 15)SIGTERM:这是 kill 命令的默认信号。它会请求进程优雅地终止,允许进程在退出前执行清理操作。进程可以选择忽略这个信号,但大多数进程会响应并正常退出。

    用途:请求进程终止。默认的信号,进程可以捕获该信号并执行清理操作后退出。

kill:通过进程id(PID)给进程发送信号

kill可以通过PID给指定进程发送想要的信号。kill不指定信号时,默认发送信号15:SIGTERM,正常退出某个进程

格式:kill 参数 信号 进程id

常用参数

参数 描述
-a 不限制命令名与进程号的对应关系
-l 显示系统支持的信号列表
-p 不发送任何信号
-s 设置向进程发送的信号

使用示例

  • 参考当前系统支持的所有信号

    [root@localhost ~]# kill -l
    
  • 正常的退出进程号为:2505的进程。下面两个命令等价

    [root@localhost ~]# kill 2505
    
    [root@localhost ~]# kill -15 2505
    
  • 强制退出进程号为:3431的进程

    [root@localhost ~]# kill -9 3431
    

killall:根据进程名关闭一组进程

常使用kill命令关闭指定PID进程号的服务,暂且不论要先用ps命令找到对应的进程号才能关闭它,就说很多服务实际会发起多个进程,对应有数个不同PID进程号,要用kill命令逐一关闭也是件麻烦事。

而将ps和kill两个命令的执行过程合二为一,就得到了超好用的killall命令。一个只需要管理员给出要关闭的服务名,就能自动找到其所对应的全部进程信息,并关闭它们。

语法格式:killall [参数] 服务名

常用参数

参数 描述
-e 进行精确匹配
-g 杀死进程所属的进程组
-i 杀死进程前询问用户是否确认
-l 显示所有已知信号列表
-o 匹配指定时间前开始的进程
-q 静默执行模式
-r 使用正规表达式匹配要杀死的进程名称
-s 用指定的进程号代替默认信号
-u 杀死指定用户的进程
-v 显示执行过程详细信息
-w 一直等待命令执行完成再退出
-y 匹配指定时间后开始的进程
--help 显示帮助信息
--version 显示版本信息

使用示例

  • 关闭指定服务所对应的全部进程

    [root@localhost rootdir]# killall httpd
    

进程优先级

概述

优先级高的进程会被CPU分配更多的CPU。值越大,优先级越低

在Linux中有两个常用的优先级值,分别是PR(Priority)和NI(Nice Value)。

  • PR是内核态优先级,他由内核根据进程的类型和属性自动分配。同时,他也是进程的实际优先级。用户无法直接分配PR优先级值

  • NI是用户态优先级,NI可设置的值是 [-20,19] 之间的整数,且NI对于PR而言,具有20个数的偏移量,也就是:PR=NI+20。通过调整NI值,用户可以影响进程的调度优先级

    默认情况下,都是普通任务进程,NI值为0。

    如果将NI指定为-20,那么该进程的用户态就拥有最高优先级

nice:以指定优先级运行进程

以指定优先级运行进程,合理分配系统资源。

Linux系统后台工作中某些不重要的进程,例如定期数据备份、自动清理垃圾等等工作,我们都可以通过nice命令调低其执行优先级,慢慢完成不用着急,把硬件资源留给重要的工作。

优先级范围为-20~19,数字越小,优先级越高。

语法格式: nice [参数] 命令或脚本名

常用参数

参数 描述
-g 匹配进程组ID
-n 设置优先级别
-p 匹配进程ID
-u 匹配用户ID
--help 显示帮助信息
--version 显示版本信息

使用示例

  • 以优先级为10的方式运行vim

    [root@localhost rootdir]# nice -n 10 vim file
    
  • 以优先级为-5的方式运行脚本文件:ShFile.sh

    [root@localhost rootdir]# nice -n -5 ./ShFile.sh
    

renice:修改进程的优先级

renice命令可以修改正在运行的进程的调度优先级。

该命令预设是以程序识别码指定程序调整其优先权,您亦可以指定程序群组或用户名称调整优先权等级,并修改所有隶属于该程序群组或用户的程序的优先权。只有系统管理者可以改变其他用户程序的优先权,也仅有系统管理者可以设置负数等级。

语法格式:renice 优先级 PID

常用参数

参数 描述
-g 指定进程组id
-p 改变该程序的优先权等级,此参数为预设值
-u 指定开启进程的用户名

使用示例

将PID为6395的进程优先级设为-20

[root@localhost rootdir]# renice -20 6395
6395 (进程 ID) 旧优先级为 0,新优先级为 -20

作业控制

当我们输入命令后,就会有相对应的进程开始运行,进程运行的过程就称为作业,默认情况下作业是在终端的前台运行,但是我们也可以把作业放到后台运行,这样就可以同时执行多个耗时的进程

将作业放到后台运行

有两种方法可以将作业放到后台

第一种,使用&符号

在命令敲完后,再在命令后面补上 & 符号,命令所对应的进程就会到后台运行,不会占领终端前台的显示

常用于耗时长、不需要人为操作和观察的进程

例如sleep命令:设定终端休眠500秒,并让他在后台运行

[root@localhost rootdir]# sleep 500s &
[1] 6777

[1]: 表示该进程在后台进程的排序,假设后台中已经有3个进程了,在添加一个进程,就会显示[4]

6777:PID

第二种,按Ctrl+z暂停作业

把进程暂停后,也会放到后台中

[root@localhost rootdir]# sleep 600s
^Z
[2]+  已停止               sleep 600s

jobs:查看终端后台作业

用于显示终端后台的作业信息。Linux系统运维人员可以使用jobs命令查看到当前系统中终端后台的任务列表及其运行状态,查看任务列表及对应的进程号码,简单方便地了解到当前有哪些正在后台运行的工作。

语法格式: jobs [参数]

常用参数

参数 描述
-l 显示作业列表及进程号
-n 仅显示自发生变化的作业
-p 仅显示其对应的进程号
-r 仅显示运行的作业
-s 仅显示暂停的作业
-x 替代原有作业的进程ID

使用示例

  • 显示全部后台运行的进程

    [root@localhost rootdir]# jobs -l
    [1]   6777 运行中               sleep 500s &
    [2]-  6843 运行中               sleep 600s &
    [3]+  6844 停止                  sleep 700s
    
  • 只显示后台运的进程id

    [root@localhost rootdir]# jobs -p
    6777
    6843
    6844
    
  • 只显示正在运行的后台进程

    [root@localhost rootdir]# jobs -r
    [1]   运行中               sleep 500s &
    [2]-  运行中               sleep 600s &
    
  • 只显示已暂停的后台进程

    [root@localhost rootdir]# jobs -s
    [3]+  已停止               sleep 700s
    

fg:将后台运行的作业放到前台

语法格式:fg 作业标识

作业标识:使用jobs命令查看

[root@localhost rootdir]# jobs -l
[1]   6777 运行中               sleep 500s &
[2]-  6843 运行中               sleep 600s &
[3]+  6844 停止                  sleep 700s

使用中括号括起来的数字就是作业标识

例如:PID为6777的进程作业标识就是1;6843的作业标识是2

使用示例

  • 将作业标识为1的作业放到前台运行

    [root@localhost rootdir]# fg 1
    

bg:让后台暂停的作业继续在后台运行

语法格式:bg 作业标识

作业标识:使用jobs命令查看

[root@localhost rootdir]# jobs -l
[1]   6777 运行中               sleep 500s &
[2]-  6843 运行中               sleep 600s &
[3]+  6844 停止                  sleep 700s

使用中括号括起来的数字就是作业标识

例如:PID为6777的进程作业标识就是1;6843的作业标识是2

使用示例:

  • 下面一个被暂停的进程在后台,作业标识为:2
[root@localhost rootdir]# sleep 600s
^Z
[2]+  已停止               sleep 600s
  • 使用bg命令让他继续运行
[root@localhost rootdir]# bg 2
[2]+ sleep 600s &
  • 使用jobs命令查看是否正常运行
[root@localhost rootdir]# jobs
[1]-  运行中               sleep 500s &
[2]+  运行中               sleep 600s &
posted @   7七柒  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示