首页 文章 精选 留言 我的

精选列表

搜索[模块],共10004篇文章
优秀的个人博客,低调大师

spark源码系列文章------shuffle模块详解

一、Basic shuffle writer实现解析 在Executor上执行shuffle Map Task时,最终会调用shuffleMapTask的runTask,核心逻辑如下: 1.从sparkEnv中获得shuffleManager; 2.从manager中获得writer 3.调用RDD开始计算,运算结果通过writer进行持久化,持久化之前通过Aggregator来确定是否需要进行Map端聚合,然后将结果通过FileShuffleManager#forMapTask的方法写入,写入完成后,会将元数据信息写入MapStatus,然后下游的Task可以通过这个MapStatus取得需要处理的数据。 这样writer通过ShuffleDependency#partitioner来获得下游partition的数量,下游的每个partition都会对应一个文件,文件名字的格式为:“shuffle_”+shuffledId+"_"+mapId+"_"+reduceId。 由于每个shuffle Map Task需要为每个下游的Task创建一个单独的文件,因此文件的数量就是number(shuffle_map_task)*number(following_task)。这样会导致创建和打开许多文件。 后来spark又引入Shuffle Consolidate Writer,原理是core上的第一个Task创建一个文件,该core上的后面的Task的shuffle操作都追加写入改文件,这样文件数量number(core)*number(following_task) 。 //todo

优秀的个人博客,低调大师

OpenStack成为NFV标准构建模块

OpenStack正在成为领先的通信服务提供商(CSP)NFV部署的基础设施编排中的实际标准,为了实现开源和开放架构的优势(即避免厂商锁定),CSP正在克服OpenStack部署的挑战(如技术不成熟和不断发展的标准)。缺乏NFV管理和编排(MANO)仍然是主要的障碍。 NFV和OpenStack OpenStack是构建和管理云计算平台的一系列开源软件工具的集合,它使得服务提供商跨计算和存储对数据中心资源池进行配置和编排。CSP能够通过NFV部署不同类型的数据中心,而不是典型的大型企业或超级规模的云。它们的计算能力分布在包括集中式核心、聚合点和局部存在点(PoP)的层中。CSP的OpenStack实现必须高度可靠,并且能够在数百个分布在不同大小的数据中心上分配工作负载。 领先CSP的OpenStack实现 领先的CSP最新发布的报告表明,他们对NFV部署中重要组成部分OpenStack的大力支持。根据OpenStack基金会的报告,CSP是OpenStack部署增长最快的部分。OpenStack是很多新兴NFV标准的关键因素,包括:CORD和OPNFV。 Verizon Verizon(与Big Switch、Dell、Red Hat合作)在其位于美国的5个数据中心实现了OpenStack云部署,该公司的NFV项目开始于2015年,依赖于提供满足公司复杂网络需求的超大规模功能和灵活性的核心和POD架构。 该公司在美国其他数据中心和汇聚站点进行额外部署,2016年在其他国家的数据中心进行部署。Verizon计划在边缘网络部署改进过的数据中心设计。Verizon公司表示,计划在未来3年内将其有线和无线网络元素大部分实现虚拟化(使用NFV和OpenStack),其中包括了数以万计的服务器规模部署。 AT&T AT&T希望通过利用NFV、SDN、OpenStack、OpenDaylight、Open vSwitch等技术在接下来的几年中实现其网络75%的虚拟化。AT&T的NFV云已经包括了10个OpenStack项目,并计划在2016年年底之前推出3个云产品。AT&T利用开源代码(包括OpenStack),期望达到将云资源的部署时间从几个月缩短到几天时间的目标。 AT&T做了大量的工作来优化OpenStack,包括扩展OpenStack以提高可靠性(运营商级可靠性),使其能够应用于新的全球网络。AT&T还使用OpenStack工具开发终端用户资源管理器,这将给AT&T的用户带来自主服务的功能,实现网络按需服务。 AT&T使用NFV和OpenStack实现的其他功能包括允许自动配置网络功能和区域发现服务的应用程序目录,区域发现服务是一种预留系统,使应用程序可以在网络上的各个地理区域运行。 其他的支持和实施OpenStack的大型CSP包括:NTT、SK电信、中国移动、中国联通、XO Communications、德国电信、瑞士电信、英国电信、Telefonica、Comcast、Time Warner Cable(时代华纳)。 OpenStack对NFV的好处 领先的CSP在部署OpenStack时,正在寻找与其他大型数据中心部署相同的优势,他们希望降低部署成本(CAPEX)和运维成本(OPEX),并提高基于云计算资源创新的灵活性和速度。大型CSP特别希望消除厂商锁定,这也是他们对OpenStack感兴趣的一个关键因素。他们对OpenStack感兴趣的其他原因包括:开源项目中固有的创新能力、广泛的ISV生态系统、开放的API。 通信服务提供商OpenStack面临的挑战 OpenStack是一个云计算管理系统,而不是一般化的网络管理系统。这意味着对CSP来说,OpenStack只是管理和编排的一部分,但其本身不是解决方案。例如,OpenStack缺少对现在使用的传统网络设备部署的许多服务和服务组件的支持。 OpenStack的一些缺点可能会随着技术的成熟和广泛的部署从而得以解决,包括: 能够扩展到数千个站点和数十万台服务器的能力部署各种OpenStack组件的一致性缺乏全面的文件 其他的挑战的实现将面临更大的难度,并且可能需要CSP特定实现,包括: 网络数据安全——特别是数据中心间东西向流量将OpenStack与CSP更广泛的NFV管理和编排解决方案联系起来的能力多厂商VNF资源分配和对服务链的支持生态 大量的企业支持OpenStack作为NFV部署的重要组成部分,包括:HPE、Dell、VMware、Cisco、Red Hat、Mirantis、Ericsson、Big Switch、Pluribus Networks、PlumGrid、Intel/Wind River、Radisys等等。 给CSP的建议 OpenStack作为提供数据中心资源的手段,现在是NFV部署的重要组件。这是一个复杂的NFV蓝图,允许CSP利用开源创新并减少厂商锁定。OpenStack需要增强可靠性、安全性,以满足领先的CSP NFV部署的特定需求。OpenStack并没有解决NFV管理和编排(MANO)的复杂挑战。 原文链接:https://www.sdxcentral.com/articles/analysis/openstack-for-nfv/2016/11/?utmsource=SDxCentral.com+Mailing+List&utmcampaign=c6d2a64eb4-SDxCentral+Newsletter+11%2F25%2F16&utm_medium=email&utmterm=0c2b6e504a2-c6d2a64eb4-81970457 本文转自d1net(转载)

优秀的个人博客,低调大师

xposed框架的Android网络监测模块

试图监控一个app所有的网络通信。 前提 : 手机root过 已成功安装xposed框架 XposedInstaller: https://github.com/rovo89/XposedInstaller 操作步骤 添加xposed框架XposedBridgeApi-54.jar包到android项目build path assets目录下添加xposed_init文件内容为com.example.xposeddiy.Test,指示入口 AndroidManifest.xml文件application标签下添加 [[meta-data android:name="xposedmodule" android:value="true" /> [[meta-data android:name="xposedminversion" android:value="40" /> [[meta-data android:name="xposeddescription" android:value="network monitor" /> hook android所有通信调用函数,代码如下 package com.example.xposeddiy; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ServerSocket; import java.net.SocketAddress; import java.net.URL; import java.util.Arrays; import java.util.Map; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import android.app.Activity; import android.app.Application; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.util.Log; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor; //web.loadUrl("http://1.1.1.0", param);web.loadUrl("http://1.1.1.1/");web.postUrl("",""); //DatagramSocket.send(packet) 发送 //DatagramSocket DatagramSocket.bind DatagramSocket.createSocket 监听 //startupSocket对应多个socket构造函数 sock.connect //ServerSocket ServerSocket.bind //SocketChannel.open(addr) ?SocketChannel.connect? //outputstream.write(byte[],int,int) //httpclient.execute(post); //urls.openConnection(); urls.openConnection(proxy); ?urls.setRequestProperty? //辅助记录,避免出现调用其他包进行监听 logcat | grep xuhu >>/sdcard/a.txt public class Test implements IXposedHookLoadPackage{ private String TARGET_APP = "com.baidu.BaiduMap"; private String[] TARGET_APPS = new String[]{"com.yek.lafaso","com.vipshop.vswxk","com.baidu.BaiduMap","com.example.t1","com.baidu.fb","com.tencent.mm","com.tencent.mtt","com.nq.mdm"}; private SharedPreferences msp = null; private Application mApp = null; private String LOG_FILENAME = "_test_network"; private boolean NETWORK = true; private boolean HTTP_DATA = true; private boolean SOCKET_DATA = true; private boolean HTTP_RESPONSE = false; @Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { if(!Arrays.asList(TARGET_APPS).contains(lpparam.packageName))return; TARGET_APP = lpparam.packageName; if(lpparam.appInfo == null || (lpparam.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) !=0){ return; }else if(true){//lpparam.isFirstApplication hookOncreate(lpparam);// if(mApp != null){ msp = mApp.getSharedPreferences(LOG_FILENAME, Activity.MODE_PRIVATE); } mLog("target", lpparam.packageName); //网络监控开始 if(NETWORK){ findAndHookConstructor(InetSocketAddress.class, String.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("网络地址", param.args[0]+":"+param.args[1]); super.beforeHookedMethod(param); } }); // findAndHookMethod("java.net.DatagramSocket", lpparam.classLoader, "send", DatagramPacket.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { DatagramPacket d = (DatagramPacket)param.args[0]; if(SOCKET_DATA){ mLog("udp发送", d.getAddress()+":"+d.getPort()+":"+new String(d.getData())); }else{ mLog("udp发送", d.getAddress()+":"+d.getPort()); } super.beforeHookedMethod(param); } }); findAndHookMethod("java.net.DatagramSocket", lpparam.classLoader, "createSocket", int.class, InetAddress.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("udp监听", ((InetAddress)param.args[1]).toString()+":"+(Integer)param.args[0]); super.beforeHookedMethod(param); } }); findAndHookMethod("java.net.DatagramSocket", lpparam.classLoader, "bind", SocketAddress.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("udp监听", ((SocketAddress)param.args[0]).toString()); super.beforeHookedMethod(param); } }); findAndHookConstructor(DatagramSocket.class, SocketAddress.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("udp监听", ((SocketAddress)param.args[0]).toString()); super.beforeHookedMethod(param); } }); // findAndHookMethod("android.webkit.WebView", lpparam.classLoader, "loadUrl", String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { String d = (String)param.args[0]; mLog("webview", d); super.beforeHookedMethod(param); } }); findAndHookMethod("android.webkit.WebView", lpparam.classLoader, "loadUrl", String.class, Map.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { String d = (String)param.args[0]; if(HTTP_DATA){ Map d1 = (Map)param.args[1]; mLog("webview", d+":"+d1.toString()); }else{ mLog("webview", d); } super.beforeHookedMethod(param); } }); findAndHookMethod("android.webkit.WebView", lpparam.classLoader, "postUrl", String.class, byte[].class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { String d = (String)param.args[0]; if(HTTP_DATA){ String d1 = new String((byte[])param.args[1]); mLog("webview", d+":"+d1); }else{ mLog("webview", d); } super.beforeHookedMethod(param); } }); // if(SOCKET_DATA){ findAndHookMethod("java.io.OutputStream", lpparam.classLoader, "write", byte[].class, int.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { byte[] d = (byte[])param.args[0]; mLog("socketdata", new String(d)); super.beforeHookedMethod(param); } }); findAndHookMethod("java.io.OutputStream", lpparam.classLoader, "write", byte[].class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { byte[] d = (byte[])param.args[0]; mLog("socketdata1", new String(d)); super.beforeHookedMethod(param); } }); } findAndHookMethod("java.nio.channels.SocketChannel", lpparam.classLoader, "open", SocketAddress.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("tcp连接", ((SocketAddress)param.args[0]).toString()); super.beforeHookedMethod(param); } }); findAndHookMethod("java.net.Socket", lpparam.classLoader, "startupSocket", InetAddress.class, int.class, InetAddress.class, int.class, boolean.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("tcp连接", ((InetAddress)param.args[0]).toString()+":"+(Integer)param.args[1]); super.beforeHookedMethod(param); } }); findAndHookMethod("java.net.Socket", lpparam.classLoader, "connect", SocketAddress.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("tcp连接", ((SocketAddress)param.args[0]).toString()); super.beforeHookedMethod(param); } }); findAndHookConstructor(ServerSocket.class, int.class, int.class, InetAddress.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("tcp监听", ((InetAddress)param.args[0]).toString()); super.beforeHookedMethod(param); } }); findAndHookMethod("java.net.ServerSocket", lpparam.classLoader, "bind", SocketAddress.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("tcp监听", ((SocketAddress)param.args[0]).toString()); super.beforeHookedMethod(param); } }); // findAndHookMethod("java.net.URL", lpparam.classLoader, "openConnection", java.net.Proxy.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { URL url = (URL) param.thisObject; mLog("urlconnp", url.toString()+":"+((Proxy)param.args[0]).toString()); super.beforeHookedMethod(param); } }); if(HTTP_DATA){ findAndHookMethod("java.net.URLConnection", lpparam.classLoader, "setRequestProperty", String.class, String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("urlconnheader", (String)param.args[0]+":"+(String)param.args[1]); super.beforeHookedMethod(param); } }); findAndHookMethod("java.net.URLConnection", lpparam.classLoader, "addRequestProperty", String.class, String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { mLog("urlconnheader", (String)param.args[0]+":"+(String)param.args[1]); super.beforeHookedMethod(param); } }); } findAndHookMethod("java.net.URL", lpparam.classLoader, "openConnection", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { URL url = (URL) param.thisObject; mLog("urlconn", url.toString()); super.beforeHookedMethod(param); } }); // hookHttpClient(lpparam); }//网络监控结束 } } public void mLog(String tag, String text){ Log.i(TARGET_APP, "xuhu"+tag+":"+text); if(msp != null){ if(HTTP_DATA){ mSharePrefer(text,tag); }else{ int i = text.indexOf("?"); if(i > 0) mSharePrefer(text.substring(0, i), tag); else mSharePrefer(text, tag); } } } public void mSharePrefer(String key, String value){ SharedPreferences.Editor editor = msp.edit(); editor.putString(key, value); editor.commit(); } public void hookHttpClient(LoadPackageParam lpparam){ findAndHookMethod("org.apache.http.impl.client.AbstractHttpClient", lpparam.classLoader, "execute", HttpHost.class, HttpRequest.class, HttpContext.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { //HttpHost host = (HttpHost) param.args[0]; HttpRequest request = (HttpRequest) param.args[1]; if (request instanceof HttpGet) { HttpGet httpGet = (HttpGet) request; mLog("httpclientGet", httpGet.getURI().toString()); if(HTTP_DATA){ Header[] headers = request.getAllHeaders(); if (headers != null) { for (int i = 0; i < headers.length; i++) { mLog("getHeader", headers[i].getName() + ": " + headers[i].getValue()); } }} } else if (request instanceof HttpPost) { HttpPost httpPost = (HttpPost) request; mLog("httpclientPost", httpPost.getURI().toString()); if(HTTP_DATA){// until get header Header[] headers = request.getAllHeaders(); if (headers != null) { for (int i = 0; i < headers.length; i++) { mLog("postHeader", headers[i].getName() + ":" + headers[i].getValue()); } } HttpEntity entity = httpPost.getEntity(); String contentType = null; if (entity.getContentType() != null) { contentType = entity.getContentType().getValue(); if (URLEncodedUtils.CONTENT_TYPE.equals(contentType)) { try { byte[] data = new byte[(int) entity.getContentLength()]; entity.getContent().read(data); String content = new String(data, HTTP.DEFAULT_CONTENT_CHARSET); mLog("postcontent",content); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (contentType.startsWith(HTTP.DEFAULT_CONTENT_TYPE)) { try { byte[] data = new byte[(int) entity.getContentLength()]; entity.getContent().read(data); String content = new String(data, contentType.substring(contentType.lastIndexOf("=") + 1)); mLog("postcontent",content); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }else{ byte[] data = new byte[(int) entity.getContentLength()]; try { entity.getContent().read(data); String content = new String(data, HTTP.DEFAULT_CONTENT_CHARSET); mLog("postcontent",content); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }//get header }else{ HttpEntityEnclosingRequestBase get = (HttpEntityEnclosingRequestBase)request; HttpEntity entity = get.getEntity(); mLog("Android-async-http", get.getURI().toString()); if(HTTP_DATA){ Header[] headers = request.getAllHeaders(); if (headers != null) { for (int i = 0; i < headers.length; i++) { mLog("Android-async-httpHeader", headers[i].getName() + ":" + headers[i].getValue()); } } if(entity!= null){ String content = EntityUtils.toString(entity); mLog("Android-async-httpcontent", content); } } } super.beforeHookedMethod(param); } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { HttpResponse resp = (HttpResponse) param.getResult(); if (resp != null && HTTP_RESPONSE) { mLog("Status Code", ""+resp.getStatusLine().getStatusCode()); Header[] headers = resp.getAllHeaders(); if (headers != null) { for (int i = 0; i < headers.length; i++) { mLog("response", headers[i].getName() + ":" + headers[i].getValue()); } } } super.afterHookedMethod(param); } }); } public void hookOncreate(LoadPackageParam lpparam){ String appClassName = lpparam.appInfo.className; if (appClassName == null) { Method hookOncreateMethod = null; try { hookOncreateMethod = Application.class.getDeclaredMethod("onCreate", new Class[] {}); } catch (NoSuchMethodException e) { e.printStackTrace(); mLog("target0", "target"); } XposedBridge.hookMethod(hookOncreateMethod, new ApplicationOnCreateHook("target0",lpparam)); }else{ Class[[?> hook_application_class = null; try { hook_application_class = lpparam.classLoader.loadClass(appClassName); if (hook_application_class != null) { Method hookOncreateMethod = hook_application_class.getDeclaredMethod("onCreate", new Class[] {}); if (hookOncreateMethod != null) { XposedBridge.hookMethod(hookOncreateMethod, new ApplicationOnCreateHook("target1",lpparam)); } } mLog("target11", "target"); } catch (Exception e) { // TODO Auto-generated catch block Method hookOncreateMethod; try { hookOncreateMethod = Application.class.getDeclaredMethod("onCreate", new Class[] {}); if (hookOncreateMethod != null) { XposedBridge.hookMethod(hookOncreateMethod, new ApplicationOnCreateHook("target2",lpparam)); } mLog("target21", "target"); } catch (NoSuchMethodException e1) { // TODO Auto-generated catch block mLog("target3", "target"); e1.printStackTrace(); } } } } private class ApplicationOnCreateHook extends XC_MethodHook { public String which; public LoadPackageParam lpparam; public ApplicationOnCreateHook(String which, LoadPackageParam lpparam){ this.which = which; this.lpparam = lpparam; } @Override public void afterHookedMethod(MethodHookParam param) throws FileNotFoundException { mLog("", which); if (!HAS_REGISTER_LISENER) { mApp = (lpparam.isFirstApplication)?(Application) param.thisObject:mApp; IntentFilter filter = new IntentFilter("xuhuafeng"); mApp.registerReceiver(new CommandBroadcastReceiver(), filter); msp = mApp.getSharedPreferences(LOG_FILENAME, Activity.MODE_PRIVATE); HAS_REGISTER_LISENER = true; } } } private boolean HAS_REGISTER_LISENER = false; }

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册