深入分析linux内核源码(面试必问的epoll技术,从内核源码出发彻底搞懂epoll)

2026-05-06 13:30:02 0

深入分析linux内核源码(面试必问的epoll技术,从内核源码出发彻底搞懂epoll)

“深入分析linux内核源码”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看深入分析linux内核源码(面试必问的epoll技术,从内核源码出发彻底搞懂epoll)!

本文目录

面试必问的epoll技术,从内核源码出发彻底搞懂epoll

epoll是linux中IO多路复用的一种机制,I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。当然linux中IO多路复用不仅仅是epoll,其他多路复用机制还有select、poll,但是接下来介绍epoll的内核实现。

events可以是以下几个宏的集合:

epoll相比select/poll的优势

epoll相关的内核代码在fs/eventpoll.c文件中,下面分别分析epoll_create、epoll_ctl和epoll_wait三个函数在内核中的实现,分析所用linux内核源码为4.1.2版本。

epoll_create用于创建一个epoll的句柄,其在内核的系统实现如下:

sys_epoll_create:

可见,我们在调用epoll_create时,传入的size参数,仅仅是用来判断是否小于等于0,之后再也没有其他用处。
整个函数就3行代码,真正的工作还是放在sys_epoll_create1函数中。

sys_epoll_create -》 sys_epoll_create1:

sys_epoll_create1 函数流程如下:

sys_epoll_create -》 sys_epoll_create1 -》 ep_alloc:


sys_epoll_create -》 sys_epoll_create1 -》 ep_alloc -》 get_unused_fd_flags:

linux内核中,current是个宏,返回的是一个task_struct结构(我们称之为进程描述符)的变量,表示的是当前进程,进程打开的文件资源保存在进程描述符的files成员里面,所以current-》files返回的当前进程打开的文件资源。rlimit(RLIMIT_NOFILE) 函数获取的是当前进程可以打开的最大文件描述符数,这个值可以设置,默认是1024。

相关视频推荐:

支撑亿级io的底层基石 epoll实战揭秘

网络原理tcp/udp,网络编程epoll/reactor,面试中正经“八股文”

学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

需要更多C/C++ Linux服务器架构师学习资料加群 812855908 获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

__alloc_fd的工作是为进程在[start,end)之间(备注:这里start为0, end为进程可以打开的最大文件描述符数)分配一个可用的文件描述符,这里就不继续深入下去了,代码如下:

sys_epoll_create -》 sys_epoll_create1 -》 ep_alloc -》 get_unused_fd_flags -》 __alloc_fd:

然后,epoll_create1会调用anon_inode_getfile,创建一个file结构,如下:

sys_epoll_create -》 sys_epoll_create1 -》 anon_inode_getfile:

anon_inode_getfile函数中首先会alloc一个file结构和一个dentry结构,然后将该file结构与一个匿名inode节点anon_inode_inode挂钩在一起,这里要注意的是,在调用anon_inode_getfile函数申请file结构时,传入了前面申请的eventpoll结构的ep变量,申请的file-》private_data会指向这个ep变量,同时,在anon_inode_getfile函数返回来后,ep-》file会指向该函数申请的file结构变量。

简要说一下file/dentry/inode,当进程打开一个文件时,内核就会为该进程分配一个file结构,表示打开的文件在进程的上下文,然后应用程序会通过一个int类型的文件描述符来访问这个结构,实际上内核的进程里面维护一个file结构的数组,而文件描述符就是相应的file结构在数组中的下标。

dentry结构(称之为“目录项”)记录着文件的各种属性,比如文件名、访问权限等,每个文件都只有一个dentry结构,然后一个进程可以多次打开一个文件,多个进程也可以打开同一个文件,这些情况,内核都会申请多个file结构,建立多个文件上下文。但是,对同一个文件来说,无论打开多少次,内核只会为该文件分配一个dentry。所以,file结构与dentry结构的关系是多对一的。

同时,每个文件除了有一个dentry目录项结构外,还有一个索引节点inode结构,里面记录文件在存储介质上的位置和分布等信息,每个文件在内核中只分配一个inode。 dentry与inode描述的目标是不同的,一个文件可能会有好几个文件名(比如链接文件),通过不同文件名访问同一个文件的权限也可能不同。dentry文件所代表的是逻辑意义上的文件,记录的是其逻辑上的属性,而inode结构所代表的是其物理意义上的文件,记录的是其物理上的属性。dentry与inode结构的关系是多对一的关系。

sys_epoll_create -》 sys_epoll_create1 -》 fd_install:

总结epoll_create函数所做的事:调用epoll_create后,在内核中分配一个eventpoll结构和代表epoll文件的file结构,并且将这两个结构关联在一块,同时,返回一个也与file结构相关联的epoll文件描述符fd。当应用程序操作epoll时,需要传入一个epoll文件描述符fd,内核根据这个fd,找到epoll的file结构,然后通过file,获取之前epoll_create申请eventpoll结构变量,epoll相关的重要信息都存储在这个结构里面。接下来,所有epoll接口函数的操作,都是在eventpoll结构变量上进行的。

所以,epoll_create的作用就是为进程在内核中建立一个从epoll文件描述符到eventpoll结构变量的通道。

epoll_ctl接口的作用是添加/修改/删除文件的监听事件,内核代码如下:

sys_epoll_ctl:

根据前面对epoll_ctl接口的介绍,op是对epoll操作的动作(添加/修改/删除事件),ep_op_has_event(op)判断是否不是删除操作,如果op != EPOLL_CTL_DEL为true,则需要调用copy_from_user函数将用户空间传过来的event事件拷贝到内核的epds变量中。因为,只有删除操作,内核不需要使用进程传入的event事件。

接着连续调用两次fdget分别获取epoll文件和被监听文件(以下称为目标文件)的file结构变量(备注:该函数返回fd结构变量,fd结构包含file结构)。

接下来就是对参数的一些检查,出现如下情况,就可以认为传入的参数有问题,直接返回出错:

当然下面还有一些关于操作动作如果是添加操作的判断,这里不做解释,比较简单,自行阅读。

在ep里面,维护着一个红黑树,每次添加注册事件时,都会申请一个epitem结构的变量表示事件的监听项,然后插入ep的红黑树里面。在epoll_ctl里面,会调用ep_find函数从ep的红黑树里面查找目标文件表示的监听项,返回的监听项可能为空。

接下来switch这块区域的代码就是整个epoll_ctl函数的核心,对op进行switch出来的有添加(EPOLL_CTL_ADD)、删除(EPOLL_CTL_DEL)和修改(EPOLL_CTL_MOD)三种情况,这里我以添加为例讲解,其他两种情况类似,知道了如何添加监听事件,其他删除和修改监听事件都可以举一反三。

为目标文件添加监控事件时,首先要保证当前ep里面还没有对该目标文件进行监听,如果存在(epi不为空),就返回-EEXIST错误。否则说明参数正常,然后先默认设置对目标文件的POLLERR和POLLHUP监听事件,然后调用ep_insert函数,将对目标文件的监听事件插入到ep维护的红黑树里面:

sys_epoll_ctl -》 ep_insert:

前面说过,对目标文件的监听是由一个epitem结构的监听项变量维护的,所以在ep_insert函数里面,首先调用kmem_cache_alloc函数,从slab分配器里面分配一个epitem结构监听项,然后对该结构进行初始化,这里也没有什么好说的。我们接下来看ep_item_poll这个函数调用:

sys_epoll_ctl -》 ep_insert -》 ep_item_poll:

ep_item_poll函数里面,调用目标文件的poll函数,这个函数针对不同的目标文件而指向不同的函数,如果目标文件为套接字的话,这个poll就指向sock_poll,而如果目标文件为tcp套接字来说,这个poll就是tcp_poll函数。虽然poll指向的函数可能会不同,但是其作用都是一样的,就是获取目标文件当前产生的事件位,并且将监听项绑定到目标文件的poll钩子里面(最重要的是注册ep_ptable_queue_proc这个poll callback回调函数),这步操作完成后,以后目标文件产生事件就会调用ep_ptable_queue_proc回调函数。

接下来,调用list_add_tail_rcu将当前监听项添加到目标文件的f_ep_links链表里面,该链表是目标文件的epoll钩子链表,所有对该目标文件进行监听的监听项都会加入到该链表里面。

然后就是调用ep_rbtree_insert,将epi监听项添加到ep维护的红黑树里面,这里不做解释,代码如下:

sys_epoll_ctl -》 ep_insert -》 ep_rbtree_insert:

前面提到,ep_insert有调用ep_item_poll去获取目标文件产生的事件位,在调用epoll_ctl前这段时间,可能会产生相关进程需要监听的事件,如果有监听的事件产生,(revents & event-》events 为 true),并且目标文件相关的监听项没有链接到ep的准备链表rdlist里面的话,就将该监听项添加到ep的rdlist准备链表里面,rdlist链接的是该epoll描述符监听的所有已经就绪的目标文件的监听项。并且,如果有任务在等待产生事件时,就调用wake_up_locked函数唤醒所有正在等待的任务,处理相应的事件。当进程调用epoll_wait时,该进程就出现在ep的wq等待队列里面。接下来讲解epoll_wait函数。

总结epoll_ctl函数:该函数根据监听的事件,为目标文件申请一个监听项,并将该监听项挂人到eventpoll结构的红黑树里面。

epoll_wait等待事件的产生,内核代码如下:

sys_epoll_wait:

首先是对进程传进来的一些参数的检查:

参数全部检查合格后,接下来就调用ep_poll函数进行真正的处理:

sys_epoll_wait -》 ep_poll:

ep_poll中首先是对等待时间的处理,timeout超时时间以ms为单位,timeout大于0,说明等待timeout时间后超时,如果timeout等于0,函数不阻塞,直接返回,小于0的情况,是永久阻塞,直到有事件产生才返回。

当没有事件产生时((!ep_events_available(ep))为true),调用__add_wait_queue_exclusive函数将当前进程加入到ep-》wq等待队列里面,然后在一个无限for循环里面,首先调用set_current_state(TASK_INTERRUPTIBLE),将当前进程设置为可中断的睡眠状态,然后当前进程就让出cpu,进入睡眠,直到有其他进程调用wake_up或者有中断信号进来唤醒本进程,它才会去执行接下来的代码。

如果进程被唤醒后,首先检查是否有事件产生,或者是否出现超时还是被其他信号唤醒的。如果出现这些情况,就跳出循环,将当前进程从ep-》wp的等待队列里面移除,并且将当前进程设置为TASK_RUNNING就绪状态。

如果真的有事件产生,就调用ep_send_events函数,将events事件转移到用户空间里面。

sys_epoll_wait -》 ep_poll -》 ep_send_events:

ep_send_events没有什么工作,真正的工作是在ep_scan_ready_list函数里面:

sys_epoll_wait -》 ep_poll -》 ep_send_events -》 ep_scan_ready_list:

ep_scan_ready_list首先将ep就绪链表里面的数据链接到一个全局的txlist里面,然后清空ep的就绪链表,同时还将ep的ovflist链表设置为NULL,ovflist是用单链表,是一个接受就绪事件的备份链表,当内核进程将事件从内核拷贝到用户空间时,这段时间目标文件可能会产生新的事件,这个时候,就需要将新的时间链入到ovlist里面。

仅接着,调用sproc回调函数(这里将调用ep_send_events_proc函数)将事件数据从内核拷贝到用户空间。

sys_epoll_wait -》 ep_poll -》 ep_send_events -》 ep_scan_ready_list -》 ep_send_events_proc:

ep_send_events_proc回调函数循环获取监听项的事件数据,对每个监听项,调用ep_item_poll获取监听到的目标文件的事件,如果获取到事件,就调用__put_user函数将数据拷贝到用户空间。

回到ep_scan_ready_list函数,上面说到,在sproc回调函数执行期间,目标文件可能会产生新的事件链入ovlist链表里面,所以,在回调结束后,需要重新将ovlist链表里面的事件添加到rdllist就绪事件链表里面。

同时在最后,如果rdlist不为空(表示是否有就绪事件),并且由进程等待该事件,就调用wake_up_locked再一次唤醒内核进程处理事件的到达(流程跟前面一样,也就是将事件拷贝到用户空间)。

到这,epoll_wait的流程是结束了,但是有一个问题,就是前面提到的进程调用epoll_wait后会睡眠,但是这个进程什么时候被唤醒呢?在调用epoll_ctl为目标文件注册监听项时,对目标文件的监听项注册一个ep_ptable_queue_proc回调函数,ep_ptable_queue_proc回调函数将进程添加到目标文件的wakeup链表里面,并且注册ep_poll_callbak回调,当目标文件产生事件时,ep_poll_callbak回调就去唤醒等待队列里面的进程。

总结一下epoll该函数: epoll_wait函数会使调用它的进程进入睡眠(timeout为0时除外),如果有监听的事件产生,该进程就被唤醒,同时将事件从内核里面拷贝到用户空间返回给该进程。

Linux下的虚拟文件系统究竟起到什么作用

Linux
允许众多不同的文件系统共存,并支持跨文件系统的文件操作,这是因为有虚拟文件系统的存在。虚拟文件系统,即VFS(Virtual File
System)是 Linux 内核中的一个软件抽象层。它通过一些数据结构及其方法向实际的文件系统如 ext2,vfat
提供接口机制。本文在简要介绍 VFS 的相关数据结构后,以文件 I/O 为切入点深入 Linux 内核源代码,追踪了 sys_open 和
sys_read 两个系统调用的代码结构,并在追踪的过程中理清了跨文件系统的文件操作的基本原理和“一切皆是文件”的口号得以实现的根本。

VFS
是一套代码框架(framework),它处于文件系统的使用者与具体的文件系统之间,将两者隔离开来。这种引入一个抽象层次的设计思想,即“上层不依赖
于具体实现,而依赖于接口;下层不依赖于具体实现,而依赖于接口”,就是著名的“依赖反转”,它在 Linux内核中随处可见。
VFS框架的设计,需要满足如下需求:
1、  为上层的用户提供统一的文件和目录的操作接口,如  open, read, write
2、  为下层的具体的文件系统,定义一系列统一的操作“接口”, 如 file_operations, inode_operations, dentry_operation,而具体的文件系统必须实现这些接口,才能融入VFS框架中。

为此,VFS 需要:
1、 定义一套文件系统的统一概念
2、 在这套概念基础上,实现提供给上层用户的操作接口,如 open, read, write 等
3、 提供一套机制,让下层的具体的文件系统可融入 VFS 框架中,如文件系统的“注册”和“安装”

VFS核心概念
1、 VFS 通过树状结构来管理文件系统,树状结构的任何一个节点都是“目录节点”
2、 树状结构具有一个“根节点”
3、 VFS 通过“超级块”来了解一个具体文件系统的所有需要的信息。具体文件系统必须先向VFS注册,注册后,VFS就可以获得该文件系统的“超级块”。
4、 具体文件系统可被安装到某个“目录节点”上,安装后,具体文件系统才可以被使用
5、 用户对文件的操作,就是通过VFS 的接口,找到对应文件的“目录节点”,然后调用该“目录节点”对应的操作接口。

关于深入分析linux内核源码和面试必问的epoll技术,从内核源码出发彻底搞懂epoll的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

深入分析linux内核源码(面试必问的epoll技术,从内核源码出发彻底搞懂epoll)

本文编辑:admin

更多文章:


指针函数的返回值(指针作为函数的返回值)

指针函数的返回值(指针作为函数的返回值)

大家好,指针函数的返回值相信很多的网友都不是很明白,包括指针作为函数的返回值也是一样,不过没有关系,接下来就来为大家分享关于指针函数的返回值和指针作为函数的返回值的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!本文目录指

2026年4月21日 05:45

myeclipse激活了还是要激活(myeclipse为什么要激活)

myeclipse激活了还是要激活(myeclipse为什么要激活)

各位老铁们好,相信很多人对myeclipse激活了还是要激活都不是特别的了解,因此呢,今天就来为大家分享下关于myeclipse激活了还是要激活以及myeclipse为什么要激活的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看

2026年7月3日 22:30

Jam在英语中到底有多少意思?Dr.jame’s work is of enormous value to the community. 先说下,to是什么意思,作用是什么,

Jam在英语中到底有多少意思?Dr.jame’s work is of enormous value to the community. 先说下,to是什么意思,作用是什么,

本篇文章给大家谈谈jam,以及Jam在英语中到底有多少意思对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。本文目录Jam在英语中到底有多少意思Dr.

2025年11月19日 01:00

phpcms 自定义字段标签模型(phpcms建议PHPCMS在评论功能上进行扩展,实现评论自定义字段)

phpcms 自定义字段标签模型(phpcms建议PHPCMS在评论功能上进行扩展,实现评论自定义字段)

“phpcms 自定义字段标签模型”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看phpcms 自定义字段标签模型(phpcms建议PHPCMS在评论功能上进行扩展,实现评论自定义字段)!本文目录phpcms建议PHPCMS

2025年10月13日 22:30

车后面有transformers(小黄蜂雪佛兰是什么车)

车后面有transformers(小黄蜂雪佛兰是什么车)

本篇文章给大家谈谈车后面有transformers,以及小黄蜂雪佛兰是什么车对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。本文目录小黄蜂雪佛兰是什

2026年3月18日 10:45

软件开发八个阶段(软件的生命周期--三个时期,八个阶段)

软件开发八个阶段(软件的生命周期--三个时期,八个阶段)

大家好,关于软件开发八个阶段很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于软件的生命周期--三个时期,八个阶段的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

2026年3月16日 10:45

android根据源码解决问题(如何解决android ndk r8c 老是重新编译源代码的问题)

android根据源码解决问题(如何解决android ndk r8c 老是重新编译源代码的问题)

大家好,android根据源码解决问题相信很多的网友都不是很明白,包括如何解决android ndk r8c 老是重新编译源代码的问题也是一样,不过没有关系,接下来就来为大家分享关于android根据源码解决问题和如何解决android n

2026年3月30日 00:30

selectorgadget下载(bootntrselector加载不成功)

selectorgadget下载(bootntrselector加载不成功)

大家好,关于selectorgadget下载很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于bootntrselector加载不成功的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,

2025年9月21日 13:30

如何输入string类型字符串(博图画面中string类型怎么输入)

如何输入string类型字符串(博图画面中string类型怎么输入)

大家好,如果您还对如何输入string类型字符串不太了解,没有关系,今天就由本站为大家分享如何输入string类型字符串的知识,包括博图画面中string类型怎么输入的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!本文目录

2026年5月6日 23:15

设计图的网站(学设计的,找图片素材的网站有哪些)

设计图的网站(学设计的,找图片素材的网站有哪些)

今天给各位分享学设计的,找图片素材的网站有哪些的知识,其中也会对学设计的,找图片素材的网站有哪些进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录学设计的,找图片素材的网站有哪些免费出装修设计图免费装修设计的网站

2026年9月3日 06:00

sw哪个版本好用?switch怎么实现成绩的范围

sw哪个版本好用?switch怎么实现成绩的范围

今天给各位分享sw哪个版本好用的知识,其中也会对sw哪个版本好用进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录sw哪个版本好用switch怎么实现成绩的范围用switch语句表示范围matlab中switch

2025年6月19日 12:15

手机网页游戏不用登录(手机上免登录国外游戏网址是什么)

手机网页游戏不用登录(手机上免登录国外游戏网址是什么)

“手机网页游戏不用登录”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看手机网页游戏不用登录(手机上免登录国外游戏网址是什么)!本文目录手机上免登录国外游戏网址是什么无需登录无需网络的游戏手机上免登录国外游戏网址是什么Craz

2026年3月11日 04:30

format函数千位分隔符(15、pandas的设置数字格式,小数位数、百分号、千位分隔符)

format函数千位分隔符(15、pandas的设置数字格式,小数位数、百分号、千位分隔符)

大家好,format函数千位分隔符相信很多的网友都不是很明白,包括15、pandas的设置数字格式,小数位数、百分号、千位分隔符也是一样,不过没有关系,接下来就来为大家分享关于format函数千位分隔符和15、pandas的设置数字格式,小

2026年4月6日 17:30

foranouting什么意思(let’s go for an outing 句中for是什么词for an outing中为什么有an修饰outing)

foranouting什么意思(let’s go for an outing 句中for是什么词for an outing中为什么有an修饰outing)

今天给各位分享let’s go for an outing 句中for是什么词for an outing中为什么有an修饰outing的知识,其中也会对let’s go for an outing 句中for是什么词for an outin

2026年3月12日 08:00

cur是哪个国家的缩写?curls是什么意思

cur是哪个国家的缩写?curls是什么意思

本篇文章给大家谈谈cur,以及cur是哪个国家的缩写对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。本文目录cur是哪个国家的缩写curls是什么意

2025年8月8日 14:45

用其他用户找不到java的变量(JAVA的环境变量)

用其他用户找不到java的变量(JAVA的环境变量)

今天给各位分享JAVA的环境变量的知识,其中也会对JAVA的环境变量进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录JAVA的环境变量Java为什么从类中没法访问主方法中定义的变量使用root用户配置的jdk,

2025年9月24日 08:00

java程序的优点有哪些(JAVA语言开发软件有什么优势)

java程序的优点有哪些(JAVA语言开发软件有什么优势)

大家好,如果您还对java程序的优点有哪些不太了解,没有关系,今天就由本站为大家分享java程序的优点有哪些的知识,包括JAVA语言开发软件有什么优势的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!本文目录JAVA语言开发

2026年7月31日 18:15

c++多线程并发(C++的多线程里的事件是怎样定义的,事件和线程有啥联系和区别)

c++多线程并发(C++的多线程里的事件是怎样定义的,事件和线程有啥联系和区别)

大家好,今天小编来为大家解答以下的问题,关于c++多线程并发,C++的多线程里的事件是怎样定义的,事件和线程有啥联系和区别这个很多人还不知道,现在让我们一起来看看吧!本文目录C++的多线程里的事件是怎样定义的,事件和线程有啥联系和区别c++

2026年9月20日 11:45

停止天然砂出口台湾(急求中国2010年10月11日起禁止出口的货物目录)

停止天然砂出口台湾(急求中国2010年10月11日起禁止出口的货物目录)

本篇文章给大家谈谈停止天然砂出口台湾,以及急求中国2010年10月11日起禁止出口的货物目录对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。本文目录

2025年6月19日 16:00

免费的翻译器(哪种翻译软件是免费的)

免费的翻译器(哪种翻译软件是免费的)

“免费的翻译器”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看免费的翻译器(哪种翻译软件是免费的)!本文目录哪种翻译软件是免费的不收费的翻译软件哪些免费翻译软件好用哪种翻译软件是免费的翻译软件是免费的有以下翻译软件目前市面上

2026年4月3日 13:00

近期文章

本站热文

electronics软件(labcenter electronics是什么软件)
2025-05-22 23:45:02 浏览:134
博客是微博吗(博客是微博吗)
2025-05-22 22:45:01 浏览:111
diversity and distribution(悬赏英语短文)
2025-05-23 16:15:02 浏览:107
ios软件开发前景(iOS就业前景怎么样)
2025-05-22 23:00:01 浏览:102
next month(有The next month这个单词吗,和 next month有什么区别)
2025-05-23 02:30:01 浏览:102
patron(patron是什么意思)
2025-05-23 10:30:02 浏览:95
标签列表

热门搜索