init与zygote的启动流程

文章目录

  • 1.init进程启动过程
    • 1.1init进程的入口函数
      • 1.1.1创建和启动所需要的文件目录
      • 1.1.2对属性进行初始化与启动属性服务
      • 1.1.3子进程信号处理函数
      • 1.1.4.重启死去的进程
      • 1.1.5.解析init.rc配置文件
    • 1.2解析init.rc配置文件
    • 1.3解析Service语句
    • 1.4init启动Zygote
      • 1.4.1start方法
    • 1.5属性服务
      • 1.5.1start_property_service
      • 1.5.2服务传理客户端请求
    • 1.6总结init进程
  • 2.Zygote启动流程
    • 2.1启动Zygote进程
      • 2.1.1runtime.start()的前戏
      • 2.1.2runtime.start()
        • 2.1.2.1JNI
      • 2.1.3ZygoteInit的main()方法的实现
        • 2.1.3.1启动SystemServer
          • 2.1.3.1.2创建子进程的作用
        • 2.1.3.2runSelectLoop
    • 2.2总结

1.init进程启动过程

init进程是Android系统中用户空间的第一个进程,进程号就是1,手机开机后,并不会直接进入init进程,在它的前面还有几步流程

  1. 启动电源,引导芯片代码从预定的地方(固化在ROM)开始,加载引导程序BootLoaderRAM,然后执行
  2. 引导程序BootLoader在Android操作系统程序开始之前的一个小程序,把系统OS拉起来并运行
  3. 启动Linux内核,寻找init.rc文件,启动init进程

上面的话有点多,而且有点难以理解,我对它的看法就是

1.启动电源

2.加载引导程序

3.启动Linux内核

4.启动init进程

1.1init进程的入口函数

刚才我们说过,在启动完linux内核之后就会寻找init.rc,然后启动init进程

我们要是找到Android的系统源码的话,我们就能发现,init目录下的所有文件就组成了init进程的整体,它的main.cpp文件就是它的入口函数

代码就不列了,我们主要知道init的这个入口函数里面到底做了哪些事情?

大致可以分为5部

1.1.1创建和启动所需要的文件目录

init的main()函数里面主要挂载了tmpfs,devpts,proc,sysfs和selinuxfs5种文件系统,这五种文件系统只有在系统运行的时候才会存在

1.1.2对属性进行初始化与启动属性服务

在main()中

property_init();

用这段代码进行初始化

后面

start_property_service();

这段进行启动属性服务

1.1.3子进程信号处理函数

main函数有一段这个代码

signal_handler_init();

不看解释我以为又初始化某个属性,结果它的作用是如果init的子进程(zygote进程)异常退出的话,init进程可能会不知道zygote进程退出了,在系统表里面还为这个进程保留了一定的信息(进程号,退出状态,运行时间等等),导致进程表的资源被浪费。为了防止zygote进程成为这样的僵尸进程,为此用这段代码,用来接收zygote进程终止的SIGCHLD信号

1.1.4.重启死去的进程

restart_process();

1.1.5.解析init.rc配置文件

parser.ParseConfig("/init.rc");

我们重点看一下如何解析init.rc配置文件的

1.2解析init.rc配置文件

init.rc这个配置文件极为重要,我们在上面不也说过了嘛,它由5种类型的语句构成的分别是

Action,Command,Service,Option,Import

其中我们上面说的zygote进程,主要是由Service类型语句构成的,Service语句用来通知init进程创建一个名为zygote的进程

1.3解析Service语句

一般情况下我们用ServiceParser来解析Service语句,

这个挺好记的,Service是服务,Parser为解析,服务+解析,所以它就是用来解析Service语句的

ServiceParser解析Service语句通常会用到两个函数

  1. ParseSection
  2. ParseLineSection

看这两个函数长得其实也差不多,但是前者是用来解析Service中的rc文件,比如init.zygote64.rc,然后就可以定义Zygote进程的属性、启动服务、设置文件权限、挂载文件系统等

但是这个并不等于就可以直接启动zygote进程,ParseSection这个函数只是Zygote进程启动的前置工作之一,它确保了Zygote进程在启动后能够正确地读取配置文件中定义的属性和服务,并执行相应的操作。但解析init.zygote64.rc文件并不代表Zygote进程已经完全启动。

后者,ParseLineSection这个函数用来解析子项,这句话的意思是,ParseLineSection是用来解析init.zygote64.rc文件中的子项的

这句话怎么理解,它和ParseSection解析的init_zygote64.rc解析的范围有什么不一样的

ParseSection函数用来解析init.zygote64.rc文件中的段落,而ParseLineSection函数用来解析init.zygote64.rc文件中的子项。在解析init.zygote64.rc文件时,Zygote进程会先使用ParseSection函数解析整个文件,然后使用ParseLineSection函数解析每个子项

在ServiceParser中我们会通过

service = std::make_unique<Service>(name,str_args);

来创建Service对象,这个Service对象就是Android中四大组件的那个Service

ServiceParser中调用完ParseSectionParseLineSection后才会调用EndSection

EndSection中会调用ServiceManagerAddService函数,这个AddService会调用

service_.emplace_back(std::move(service));

这个就是把内容填充到service后将service对象加入vector类型的service链表中

1.4init启动Zygote

在刚才我们已经将Service放入到Vector类型service链表中

既然放入到了链表中,那么就说明service对象很多,所以我们现在的任务就是从service链表中选出那个zygote,因为zygoteclassNamemain,所以我们从链表中找到classNamemain的那个就可以了

因为zygote对应的init.zygote64.rc并没有设置disabled选项,所以我们得通过调用start方法,才能启动zygote

1.4.1start方法

我们刚才说了因为没有设置disabled选项所以我们必须得调用start方法才能启动zygote,所以我们来看来看看start的方法是怎么实现的

1.首先它会判断servicce是否是否启动,如果启动了的话,那就不管了直接返回一个false,如果没有启动,那么就进行下面的操作

2.它判断子进程有没有启动,如果没有启动那么就通过fork()来创建一个子进程(这个在fork()在操作系统里面经常遇见),并返回pid的值,如果pid的值为0,那么就通过execve函数的调用,启动service的子进程

3.在启动子进程的同时会进入该Service的main()函数,如果该servicezygote则会调用runtimestart方法,这样就成功启动了zygote

当时我有两个地方不太懂,

第一个是为什么要创建一个子进程,第二个是pid==0这意味着什么?

结合网上查到的资料与我自己的理解

对于为什么要创建一个子进程,理解是当应用程序进程启动时,Zygote 进程会派生出一个新的应用程序进程,并将应用程序的类和资源加载到该进程的 Dalvik 虚拟机中。起到提高启动速度和效率与降低资源浪费的作用

而pid0则是因为在Android系统中,进程ID0表示虚拟进程,它不占用系统资源,而是用来管理系统的一些特殊任务。这里的Zygote进程与后面的Binder驱动程序就是和这个有关

对了在嵌入式里面也有pid,但那是一个算法和这个没有关系

1.5属性服务

这里的属性服务指的是即使系统或软件重启,还是可以根据之前注册表中的记录,进行相应的初始化工作

这个和之前讲的Activity中的一个特别相似

在讲Activity中,如果我们不使用ViewModel的话,在把手机从竖屏到横屏的时候,它会执行onDestroy(),但是假如我们那个Activity中有EditText,EditText里面有TextView,为什么TextView不会丢失

我们把它的生命周期打印下来

 D/TAG: onCreateD/TAG: onStartD/TAG: onResumeD/TAG: onPauseD/TAG: onStopD/TAG: onSaveInstanceStateD/TAG: onDestroyD/TAG: onCreateD/TAG: onStartD/TAG: onRestoreInstanceStateD/TAG: onResume

我们注意一下,这里有一个onSaveInstanceStateonRestoreInstanceState,就是因为有这个,在旋转的时候通过onSaveInstanceState把我们的EditText中的数据保存下来又通过onRestoreInstanceState将保存的数据弄到EditText中

这个的作用和属性服务很像

我们在init进程的入口函数的代码中也讲过,init的其中一个功能就是对属性进行初始化与启动属性服务

property_init();

start_property_service();

其中property_init()在《进阶解密》中并没有讲多少只是提了一嘴可以初始化属性内存区域

主要讲的是start_property_service

我们就主要看看start_property_service主要干了些什么

1.5.1start_property_service

简单说一下就是4个点

  1. 创建一个非阻塞的socket
  2. 调用listen方法对property_set_fd进行监听,使socket成为一个属性服务
  3. property_set_fd放入epoll进行监听
  4. property_set_fd有数据到来的时候,init进程会调用handler_property_set_fd进行处理

首先socket我们都很清楚,它是IPC的一个方式,我用Java写聊天室就是通过socket写的

主要是第二点和第三点到底是什么意思,listen和epoll感觉都是对property_set_fd进行监听,那么这两个监听又有什么不同呢?

我搜了一下发现,listen主要监听的是property_set_fd的属性

而epoll监听的是多个套接字,比如监听IPC

chatgpt给出的解释是

listen_socket() 函数用于创建 Unix 套接字并监听属性变化的通知,而 epoll_wait() 函数用于监听套接字状态的变化,并作出相应的响应。

那么就把它理解成listen比epoll多一个创建套接字的过程,epoll又比listen多一个响应的过程

在handler的那块我写过,当MessageQueue没有Message传递给Looper的时候,在epoll会调用epoll.await来阻塞主线程,这一块联系到一起了

1.5.2服务传理客户端请求

我们上面说了当property_set_fd有数据到来的时候,init进程会调用handler_property_fd进行处理

系统属性分为2种类型,一种是普通属性,一种是控制属性。控制属性的一个例子就是开机动画

既然属性都分为这两种了,那么处理属性的也分为两种

一种是处理普通属性,一种是处理控制属性一般以 ctl.开头的就是控制属性

因为控制的英文单词是control

如果是普通属性则会对普通属性进行修改,首先判断属性合不合法,然后判断属性存不存在,不存在就添加,存在就更新

1.6总结init进程

init进程主要就是干了以下三点

  1. 创建和挂载启动所需要的文件目录
  2. 初始化和启动属性
  3. 解析init.rc配置文件并启动zygote进程

2.Zygote启动流程

2.1启动Zygote进程

2.1.1runtime.start()的前戏

在刚才init的启动流程中我们还记得,Zygote的启动是在init解析init.rc文件后,解析service,然后在service链表中找到那个className为main的service,调用它的start方法,start方法在内部会先判断它是否启动这个service,没有启动的话判断是否有service子进程在没有的情况下先通过fork创建子进程然后找到pid==0的那个进程启动service的子进程然后进入service的main函数,调用runtime.start()来启动Zygote进程

但是runtime是怎么调用的我们并不是多熟悉,所以了解Zygote的第一步,就是先了解一下runtime在调用之前它的那个函数都经历过什么?

我们先找到frameworks/base/cmds.app_process/app_main.cpp中找到代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3oRtqeBm-1686922381178)(../../assets/QQ图片20230616192925.jpg)]

这段代码可以理解做了3件事。

第一件事是判断main函数在不在zygote进程中,如果在的话把标志位设置为true

第二件事是如果不在zygote进程中,那么就再判断是否运行在SystemServer进程中,是的话把它的相关标志位标志为true

第三件事是如果zygote进程中的标志为true,那么就调用runtimestart

然后我们看看runtime.start()代码里面的东西

2.1.2runtime.start()

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{.....
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { //1 启动虚拟机return;
}
onVmCreated(env); //2 创建虚拟机/** Register android functions.*/
if (startReg(env) < 0) { //3 注册Java方法ALOGE("Unable to register all android natives\n");return;
}/** We want to call main() with a String array with arguments in it.* At present we have two arguments, the class name and an option string.* Create an array to hold them.*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);//4 获得类名
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);for (size_t i = 0; i < options.size(); ++i) {jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());assert(optionsStr != NULL);env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}/** Start VM.  This thread becomes the main thread of the VM, and will* not return until the VM exits.*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName); //5 找到类名对应的类--ZygoteInit
if (startClass == NULL) {ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);/* keep going */
} else {jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");//6 找到对应类的main方法if (startMeth == NULL) {ALOGE("JavaVM unable to find main() in '%s'\n", className);/* keep going */} else {env->CallStaticVoidMethod(startClass, startMeth, strArray);//7 调用找到的main方法,从这里开始也进入了Java框架层#if 0if (env->ExceptionCheck())threadExitUncaughtException(env);
#endif}}......
}

我们是不是都会有点疑虑,我们的Android代码要么用java要么用kotlin,在native层才用c++语言,那什么时候native层才会结束

答案等会儿就可以揭晓了

我们可以看到runtime.start()代码的内部它先创建了一个Java虚拟机,然后在java虚拟机中注册了JNI方法

通过JNI方法,我们调用ZygoteInit的main方法,成功让Zygote由Native层转到Java框架层

这后面我们看到的代码就是java的了

我们本来应该乘胜追击看看ZygoteInit里面的main()方法是怎么实现的,但是在此之前,我们先来看看什么叫JNI?

2.1.2.1JNI

JNI(Java Native Interface)方法是一种 Java 编程语言本地(即非 Java)编程语言交互的机制。它允许 Java 应用程序调用本地代码(通常是 C 或 C++ 代码),从而实现对底层系统或硬件的直接访问

2.1.3ZygoteInit的main()方法的实现

代码有点长,所以我还是用我自己的表达来叙述,

一般代码太长的,我也不会去看它,而是去看相关的注释

它的第一步是创建一个Server端Socket

我们是通过

zygoteServer.registerServerSocket(socketName);

来完成,我们可以看见它是通过这个ZygoteServer来调用registerServerSocket

然后第二步是

preload(bootTimingsTraceLog);

这步是用来预加载类和资源

第三是调用

startSystemServer(abiList,socketName,zygoteServer);

我们把上面注册Server端的Socket还有socketName还有abiList这3个参数传入来启动SystemServer

第四步通过

zygoteServer.runSelectLoop(abiList);

用这个方法来等待AMS请求

第一步创建Server端的Socket和第二步预加载类和资源这个没什么说的,我们重点来看3,4这2个步骤

2.1.3.1启动SystemServer

我们通过创建一个args[]数组,因为我们是要启动SystemServer,所以很明显这个数组是用来存储启动SystemServer的参数的

然后把这个数组封装成forkSystemServer函数所需要的参数,通过这些参数,我们可以创建子进程,如果创建的这个子进程的pid==0就代表当前代码运行在新创建的子进程中,在这个基础上,我们调用handlerSystemServerProcess()来处理SystemServer进程

这样启动就算结束了

但是我有一点不明白的就是当时候我们init进程启动的时候创建了一个子进程,然后当它的pid==0的时候才能执行start方法

然后在启动SystemServer的过程中我们也要创建一个子进程,当它的子进程的pid==0的时候才能继续进行**handlerSystemServerProcess()**来进行下面的处理

那么这个创建子进程到底是在干什么

2.1.3.1.2创建子进程的作用

Zygote 进程是一个特殊的进程,它主要负责启动其他的 Java 进程和应用程序。在启动一个新的进程时,如果每次都需要重新启动一个 Zygote 进程,会导致系统资源的浪费和进程启动速度的下降。因此,在 Android 系统中,通常会使用 fork() 函数来创建一个新的进程,从而提高进程启动速度和系统资源利用率。

forkSystemServer() 函数的作用就是使用 fork() 函数来创建一个新的进程,并在新进程中执行 handlerSystemServerProcess() 函数。这个新进程就是 SystemServer 进程,它是 Android 系统中非常重要的进程之一,负责管理系统服务、应用程序和其他系统组件。使用 forkSystemServer() 函数可以快速启动 SystemServer 进程,从而提高 Android 系统的启动速度和稳定性。

另外,forkSystemServer() 函数还实现了子进程和父进程之间的通信,通过 socket 描述符来共享信息。这种方式可以实现进程间的同步和数据共享,从而提高系统的协作能力和效率。

2.1.3.2runSelectLoop

我们看到Loop我们就可以猜到它肯定又是一个进行无限循环然后把相关消息交给其它进行处理

果不其然

我们在它的源码看到的最显眼的就是那个

while(true)

runSelectLoop的主要作用就是监听刚才创建Server端的Socket,通过这个runSelectLoop无限循环来等待AMS的请求并创建新的应用程序的进程

2.2总结

我们以它处于Native还是Java框架层为分界点,分为两个时期

第一段是仍然处于Native层,我们先判断service的main函数在不在Zygote进程,如果在的话,给它相关的标志设置为true。如果不在,但是它在SystemServer这个进程中,那么我们把这个的相关标志设置为true。在Zygote的相关标志为true的情况下,我们启动Zygote进程

start的内部我们会创建Java虚拟机,然后注册JNI方法,通过JNI方法 我们调用ZygoteInit的main方法,成功让Zygote由Native层转到Java框架层

从此第一阶段结束

第二阶段就是我们通过JNI方法创建ZygoteInitmain方法之后进入java框架层

在这里面我们主要进行了4个操作

第一个操作是创建了Server端的Socket,以供后面第四步的runSelectLoop使用

第二个操作就是预加载类和资源

第一个和第二个操作没有怎么讲,因为感觉确实没啥讲的

第三个操作应该是监听,但是它的方法竟然在启动SystemServer后面就很离谱,监听调用的就是runSelectedLoop()方法,监听第一步获得的Server端的Socket然后等待AMS请求并对相关的套接字做出回应

第四个操作是启动SystemServer,我们通过创建子进程,然后判断子进程的pid是否为0,如果为0的话,那么我们就**handlerSystemServerProcess()**来处理SystemServer。(这个步骤和init启动Zygote的步骤极为相似)

至此Zygote进程的启动流程结束

我们可以看出它的主要的作用

1.从Native层跳到Java的虚拟机层

2.无限循环监听AMS的请求,并作出回应

3.启动SystemServer
main方法之后进入java框架层

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

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

相关文章

得物前端巡检平台的建设和应用(建设篇)

1.背景 我们所在的效能团队&#xff0c;对这个需求最原始的来源是在一次“小项目”的评审中&#xff0c;增长的业务同学提出来的&#xff0c;目的在于保障前端页面稳定性的同时减少大量测试人力的回归成本。 页面稳定性提升&#xff0c;之前迭代遇见过一些C端的线上问题&…

家人们,谁懂啊,我面试面到了前公司的领导

最近面试&#xff0c;居然面到了刚毕业时的领导。 他认出了我&#xff0c;嬉笑、挑逗的问我现在在这家公司**“混”**的怎么样&#xff1f;还记得当初他待我不薄不&#xff1f; 对于提问&#xff0c;他回答得颠三倒四。 了解到他在之前的几家小公司都过着生活安逸、薪资稳定…

最实用的自媒体爆文采集工具,简单易出爆文

自媒体想要变现&#xff0c;最重要的路径就是获取流量&#xff0c;让文章\视频的阅读量\播放量能够提升&#xff0c;因此&#xff0c;学会利用自媒体工具产出爆款内容就很重要&#xff0c;今天给大家介绍一下&#xff0c;2021年&#xff0c;最实用的自媒体爆文采集工具&#xf…

腾讯大逆转阿里,夺回港股王,马化腾“拍了拍”马云

和“中国首富”这样的个人荣誉相比&#xff0c;相信腾讯创始人马化腾更看重&#xff0c;腾讯公司在江湖中的地位。 2019年11月26日&#xff0c;阿里巴巴集团&#xff08;9988.HK&#xff09;在港交所二次上市前&#xff0c;港股“市值王”一直是腾讯&#xff0c;且领先其他公司…

如何添加马云,马化腾,李彦宏的微信

让马化腾出现在你的微信聊天里面 首先声明不是 PS&#xff0c; 我不会 PS 的&#xff0c;这是程序截图&#xff1a; 如下图&#xff1a; 程序源代码&#xff1a; http://git.oschina.net/LittleDY/isWeiXin 我在他的基础上&#xff0c;重新设计了图片和聊天记录。图片来自百度…

马云曾经偶像,终于把阿里留下的 1400 亿败光了

作者&#xff1a;张一弛 来源&#xff1a;金错刀&#xff08;ID&#xff1a;ijincuodao&#xff09; 阿里这个金矿&#xff0c;终于被雅虎花光了。 三天前&#xff0c;Altaba宣布将清算和解散&#xff0c;其所持有的阿里巴巴集团股份将对外转让&#xff0c;拟转让的阿里巴巴股份…

如何写一篇法学论文?

我本科是工科专业&#xff0c;千辛万苦跨考到法学&#xff0c;没想到这是噩梦的开端。工科到社科的跨度比想象中大了很多&#xff0c;不再有正确的算式&#xff0c;不再有精细的实验操作&#xff0c;我面对的是一篇篇无从下手的论文。研一上学期的我完全就是个彻头彻尾的学渣&a…

华为认证HCIA-Kunpeng Application Developer单选习题总结

最近参加了华为HCIA-Kunpeng Application Developer的认证考试。所以分享一下在培训和备考过程中做的一些习题。 ▣ 考试总共90分钟&#xff0c;有60个题。分别有单选、多选和判断。总分1000分&#xff0c;600分过。 单选练习题 1.TaiShan服务器支持哪个中标麒麟版本&#xf…

用Azure认知服务开发一个语音翻译机,学英文很爽快

最近CSDN开展了《0元试用微软 Azure人工智能认知服务&#xff0c;精美礼品大放送》&#xff0c;当前目前活动还在继续&#xff0c;热心的我已经第一时间报名参与&#xff0c;只不过今天才有时间实际的试用。 目前活动要求博文形式分享试用语音转文本、文本转语音、语音翻译、文…

对话式文档审阅:积极拥抱大型语言模型,实在智能Chat-IDP开启内测

以ChatGPT为代表的自然语言处理大模型技术大火出圈&#xff0c;微软、谷歌、百度系等生成式大模型接连发布和不断升级优化&#xff0c;人工智能的快速发展&#xff0c;进一步促使AI产业带动生产力变革&#xff0c;正式拉开一个AI时代的全新序幕。 国内多家头部AI企业都在加大大…

阿里达摩院开源大型端到端语音识别工具包FunASR | 弥合学术与工业应用之间的差距

本文首发于微信公众号 CVHub&#xff0c;严禁私自转载或售卖到其他平台&#xff0c;违者必究。 Title: FunASR: A Fundamental End-to-End Speech Recognition Toolkit PDF: https://arxiv.org/pdf/2305.11013v1.pdf Code: https://github.com/alibaba-damo-academy/FunASR 导读…

利用科大讯飞语音合成模块SDK实现ROS语音交互

利用科大讯飞语音合成模块SDK实现ROS语音交互 本文内容与CSDN博主「AI Chen」的原创文章相同&#xff0c;可以直接参考原文&#xff1a;https://blog.csdn.net/qq_39400324/article/details/125351722快速链接 本文目的在于记录学习过程&#xff0c;作为笔记。 本文标记为转载。…

华为鲲鹏HCIA考试-练习02

文章目录 单选题多选题判断题其他练习&#xff1a;模拟考试&#xff1a; 单选题 镜像导出时&#xff0c;支持的最大镜像文件大小是? A、128GB B、64GB C、32GB D、256GB A通过源码编译制作软件包时&#xff0c;默认会把打包后的rpm包放在以下哪个目录下? A、BUILD B、SPECS …

人工智能术语库分享(包括彩云小译分享码)【更新链接】

来源&#xff1a;https://github.com/jiqizhixin/Artificial-Intelligence-Terminology-Database 内容介绍 经常使用彩云小译翻译文献&#xff0c;在网上找到这个术语库的时候很高兴&#xff0c;里面包含了很多机器学习的词汇。 我将其整理成了excel表格&#xff0c;可进行导入…

Meta 开源语音 AI 模型支持 1,100 多种语言

自从ChatGPT火爆以来&#xff0c;各种通用的大型模型层出不穷&#xff0c;GPT4、SAM等等&#xff0c;本周一Meta 又开源了新的语音模型MMS&#xff0c;这个模型号称支持4000多种语言&#xff0c;并且发布了支持1100种语言的预训练模型权重&#xff0c;最主要的是这个模型不仅支…

重磅!普惠AI--华为云语音语义万次调用1元购,有奖问答@评论区等你来!

活动快速入口&#xff1a;https://activity.huaweicloud.com/language_speech_promotion0.html 语音交互与自然语言处理 语音交互是一种人机交互方式&#xff0c;以开放API的方式提供给用户&#xff0c;用户通过实时访问和调用API获取语音交互结果。自然语言处理是针对各类企…

华为OD机试用Python实现 -【云短信平台优惠活动】(2023-Q1 新题)

华为OD机试题 华为OD机试300题大纲云短信平台优惠活动题目描述输入描述输出描述示例一输入输出说明示例二输入输出说明Python 代码实现代码编写思路华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看…

华为认证HCIA-Kunpeng Application Developer多选习题总结

最近参加了华为HCIA-Kunpeng Application Developer的认证考试。所以分享一下在培训和备考过程中做的一些习题。 ▣ 考试总共90分钟&#xff0c;有60个题。分别有单选、多选和判断。总分1000分&#xff0c;600分过。 多选练习题 1.TaiShan 200机架服务器包含哪些型号&#xf…

【愚公系列】华为云系列之ModelArts搭建中文语音识别系统

文章目录 前言1.ModelArts是什么 一、语音识别技术概述1.语音识别概述2.语音识别的一般原理3.信号处理与特征提取方法3.1 MFCC 4.基于深度学习的声学模型DNN-HMM 二、DFCNN全序列卷积神经网络介绍三、Transformer原理四、使用ModelArts快速上手训练DFCNNTransformer模型完成中文…

软件开发工程师个人简历模板3篇

软件开发工程师个人简历模板篇1 姓 名&#xff1a; 张先生 性 别&#xff1a; 男 婚姻状况&#xff1a; 未婚 民 族&#xff1a; 汉族 户 籍&#xff1a; 广东-珠海 年 龄&#xff1a; 28 现所在地&#xff1a; 广东-珠海 身 高&#xff1a; 168cm 希望地区&#xff1a; …