misc_3

本文详细解析了Android中Handler的工作原理,包括Handler、Message、Looper和MessageQueue的关系,以及如何在子线程中正确使用Handler。文章介绍了Handler的由来、作用、更新UI线程的使用方法,以及Handler和Looper的构造函数、消息发送机制和Looper的循环处理过程。
<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 1、Handler的由来
 </font>
</td>
</tr>
</table>
##  
   当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程。

  Android的UI操作并不是线程安全的(出于性能优化考虑),意味着如果多个线程并发操作UI线程,可能导致线程安全问题。 

  为了解决Android应用多线程问题—Android平台只允许UI线程修改Activity里的UI组建,就会导致新启动的线程无法改变界面组建的属性值。

  **简单的说:**当主线程队列处理一个消息超过5秒,android 就会抛出一个 ANP(无响应)的异常,所以,我们需要把一些要处理比较长的消息,放在一个单独线程里面处理,把处理以后的结果,返回给主线程运行,就需要用的Handler来进行线程建的通信。

<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 2、Handler的作用
 </font>
</td>
</tr>
</table>
##  

2.1 让线程延时执行

主要用到的两个方法:

 - final boolean	postAtTime(Runnable r, long uptimeMillis)

 - final boolean	postDelayed(Runnable r, long delayMillis)

2.2 让任务在其他线程中执行并返回结果

分为两个步骤:

 - 在新启动的线程中发送消息

  使用Handler对象的sendMessage()方法或者SendEmptyMessage()方法发送消息。

 - 在主线程中获取处理消息

  重写Handler类中处理消息的方法(void handleMessage(Message msg)),当新启动的线程发送消息时,消息发送到与之关联的MessageQueue。而Hanlder不断地从MessageQueue中获取并处理消息。

<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 3、Handler更新UI线程一般使用
 </font>
</td>
</tr>
</table>
##  

  

 - 首先要进行Handler 申明,复写handleMessage方法( 放在主线程中)

```
private Handler handler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			// TODO 接收消息并且去更新UI线程上的控件内容
			if (msg.what == UPDATE) {
				// 更新界面上的textview
				tv.setText(String.valueOf(msg.obj));
			}
			super.handleMessage(msg);
		}
	};
```

 - 子线程发送Message给ui线程表示自己任务已经执行完成,主线程可以做相应的操作了。

```
new Thread() {
			@Override
			public void run() {
				// TODO 子线程中通过handler发送消息给handler接收,由handler去更新TextView的值
				try {
					   //do something
						
						Message msg = new Message();
						msg.what = UPDATE;					
						msg.obj = "更新后的值" ;
						handler.sendMessage(msg);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}.start();
```

<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 4、Handler原理分析
 </font>
</td>
</tr>
</table>
##  

4.1  Handler的构造函数

> ① public Handler()
② public Handler(Callbackcallback)
③ public Handler(Looperlooper)
④ public Handler(Looperlooper, Callbackcallback)  


 - 第①个和第②个构造函数都没有传递Looper,这两个构造函数都将通过调用Looper.myLooper()获取当前线程绑定的Looper对象,然后将该Looper对象保存到名为mLooper的成员字段中。  
  下面来看①②个函数源码:
  

```
113    public Handler() {
114        this(null, false);
115    }

127    public Handler(Callback callback) {
128        this(callback, false);
129    }

//他们会调用Handler的内部构造方法

188    public Handler(Callback callback, boolean async) {
189        if (FIND_POTENTIAL_LEAKS) {
190      final Class<? extends Handler> klass = getClass();
191      if ((klass.isAnonymousClass() ||klass.isMemberClass()
         || klass.isLocalClass()) &&
192                    (klass.getModifiers() & Modifier.STATIC) == 0) {
193                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
194                    klass.getCanonicalName());
195            }
196        }
197/************************************
198        mLooper = Looper.myLooper();
199        if (mLooper == null) {
200            throw new RuntimeException(
201                "Can't create handler inside thread that has not called Looper.prepare()");
202        }
203        mQueue = mLooper.mQueue;
204        mCallback = callback;
205        mAsynchronous = async;
206    }

```

    我们看到暗红色的重点部分:

  通过Looper.myLooper()获取了当前线程保存的Looper实例,又通过这个Looper实例获取了其中保存的MessageQueue(消息队列)。**每个Handler 对应一个Looper对象,产生一个MessageQueue**
  

 - 第③个和第④个构造函数传递了Looper对象,这两个构造函数会将该Looper保存到名为mLooper的成员字段中。 
  下面来看③④个函数源码:

```
136    public Handler(Looper looper) {
137        this(looper, null, false);
138    } 

147    public Handler(Looper looper, Callback callback) {
148        this(looper, callback, false);
149    }
//他们会调用Handler的内部构造方法

227    public Handler(Looper looper, Callback callback, boolean async) {
228        mLooper = looper;
229        mQueue = looper.mQueue;
230        mCallback = callback;
231        mAsynchronous = async;
232    }

```

 - 第②个和第④个构造函数还传递了Callback对象,Callback是Handler中的内部接口,需要实现其内部的handleMessage方法,Callback代码如下:

```
80     public interface Callback {
81         public boolean More ...handleMessage(Message msg);
82     }
```

  Handler.Callback是用来处理Message的一种手段,如果没有传递该参数,那么就应该重写Handler的handleMessage方法,也就是说为了使得Handler能够处理Message,我们有两种办法: 
  
 1. 向Hanlder的构造函数传入一个Handler.Callback对象,并实现Handler.Callback的handleMessage方法  
  
 2. 无需向Hanlder的构造函数传入Handler.Callback对象,但是需要重写Handler本身的handleMessage方法  
   
   也就是说无论哪种方式,我们都得通过某种方式实现handleMessage方法,这点与Java中对Thread的设计有异曲同工之处。 

4.2 Handle发送消息的几个方法源码

```
   public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
```

```
   public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
```

```
 public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
```

```
 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
```

我们可以看出他们最后都调用了sendMessageAtTime(),然后返回了enqueueMessage方法,下面看一下此方法源码:

```
626    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
      //把当前的handler作为msg的target属性
627        msg.target = this;
628        if (mAsynchronous) {
629            msg.setAsynchronous(true);
630        }
631        return queue.enqueueMessage(msg, uptimeMillis);
632    }
```

在该方法中有两件事需要注意:  

1. msg.target = this 

   该代码将Message的target绑定为当前的Handler
2. queue.enqueueMessage
  
  变量queue表示的是Handler所绑定的消息队列MessageQueue,通过调用queue.enqueueMessage(msg, uptimeMillis)我们将Message放入到消息队列中。

过下图可以看到完整的方法调用顺序: 

![这里写图片描述](https://img-blog.youkuaiyun.com/20160516125245477) 

<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 5、Looper原理分析
 </font>
</td>
</tr>
</table>
##  

  我们一般在主线程申明Handler,有时我们需要继承Thread类实现自己的线程功能,当我们在里面申明Handler的时候会报错。其原因是主线程中已经实现了两个重要的Looper方法,下面看一看ActivityThread.java中main方法的源码:

```
public static void main(String[] args) {
            //......省略
5205        Looper.prepareMainLooper();//>
5206
5207        ActivityThread thread = new ActivityThread();
5208        thread.attach(false);
5209
5210        if (sMainThreadHandler == null) {
5211            sMainThreadHandler = thread.getHandler();
5212        }
5213
5214        AsyncTask.init();
5215
5216        if (false) {
5217            Looper.myLooper().setMessageLogging(new
5218   LogPrinter(Log.DEBUG, "ActivityThread"));
5219        }
5220
5221        Looper.loop();//>
5222
5223        throw new RuntimeException("Main thread loop unexpectedly exited");
5224    }
5225}
```

5.1 首先看prepare()方法

  

```
70     public static void prepare() {
71         prepare(true);
72     }
73 
74     private static void prepare(boolean quitAllowed) {
     //证了一个线程中只有一个Looper实例
75         if (sThreadLocal.get() != null) {
76             throw new RuntimeException("Only one Looper may be created per thread");
77         }
78         sThreadLocal.set(new Looper(quitAllowed));
79     }
```
该方法会调用Looper构造函数同时实例化出MessageQueue和当前thread.

```
186    private Looper(boolean quitAllowed) {
187        mQueue = new MessageQueue(quitAllowed);
188        mThread = Thread.currentThread();
189    } 

182    public static MessageQueue myQueue() {
183        return myLooper().mQueue;
184    }

```


  prepare()方法中通过ThreadLocal对象实现Looper实例与线程的绑定。(不清楚的可以查看 [ThreadLocal的使用规则和源码分析](http://blog.youkuaiyun.com/amazing7/article/details/51313851)) 


5.2  loop()方法

  

```
109    public static void loop() {
110        final Looper me = myLooper();
111        if (me == null) {
112            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
113        }
114        final MessageQueue queue = me.mQueue;
115
118        Binder.clearCallingIdentity();
119        final long ident = Binder.clearCallingIdentity();
120
121        for (;;) {
122            Message msg = queue.next(); // might block
123            if (msg == null) {
124               
125                return;
126            }
127
129            Printer logging = me.mLogging;
130            if (logging != null) {
131                logging.println(">>>>> Dispatching to " + msg.target + " " +
132                        msg.callback + ": " + msg.what);
133            }
//重点****
135            msg.target.dispatchMessage(msg);
136
137            if (logging != null) {
138                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
139            }
140
142            // identity of the thread wasn't corrupted.
143            final long newIdent = Binder.clearCallingIdentity();
144            if (ident != newIdent) {
145                Log.wtf(TAG, "Thread identity changed from 0x"
146                        + Long.toHexString(ident) + " to 0x"
147                        + Long.toHexString(newIdent) + " while dispatching to "
148                        + msg.target.getClass().getName() + " "
149                        + msg.callback + " what=" + msg.what);
150            }
151
152            msg.recycleUnchecked();
153        }
154    }
```
   首先looper对象不能为空,就是说loop()方法调用必须在prepare()方法的后面。

 Looper一直在不断的从消息队列中通过MessageQueue的next方法获取Message,然后通过代码msg.target.dispatchMessage(msg)让该msg所绑定的Handler(Message.target)执行dispatchMessage方法以实现对Message的处理。 

Handler的dispatchMessage的源码如下:

```
93     public void dispatchMessage(Message msg) {
94         if (msg.callback != null) {
95             handleCallback(msg);
96         } else {
97             if (mCallback != null) {
98                 if (mCallback.handleMessage(msg)) {
99                     return;
100                }
101            }
102            handleMessage(msg);
103        }
104    }
```
   我们可以看到Handler提供了三种途径处理Message,而且处理有前后优先级之分:首先尝试让postXXX中传递的Runnable执行,其次尝试让Handler构造函数中传入的Callback的handleMessage方法处理,最后才是让Handler自身的handleMessage方法处理Message。


<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 6、如何在子线程中使用Handler
 </font>
</td>
</tr>
</table>
##  

    Handler本质是从当前的线程中获取到Looper来监听和操作MessageQueue,当其他线程执行完成后回调当前线程。

  子线程需要先prepare()才能获取到Looper的,是因为在子线程只是一个普通的线程,其ThreadLoacl中没有设置过Looper,所以会抛出异常,而在Looper的prepare()方法中sThreadLocal.set(new Looper())是设置了Looper的。

6.1 实例代码

 定义一个类实现Runnable接口或继承Thread类(一般不继承)。

```
    class Rub implements Runnable {  
  
        public Handler myHandler;  
        // 实现Runnable接口的线程体 
        @Override  
        public void run() {  
        	
         /*①、调用Looper的prepare()方法为当前线程创建Looper对象并,
          创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue*/
            Looper.prepare();  
            
            /*.②、创建Handler子类的实例,重写HandleMessage()方法,该方法处理除当前线程以外线程的消息*/
             myHandler = new Handler() {  
                @Override  
                public void handleMessage(Message msg) {  
                    String ms = "";  
                    if (msg.what == 0x777) {  
                     
                    }  
                }  
  
            };  
            //③、调用Looper的loop()方法来启动Looper让消息队列转动起来
            Looper.loop();  
        }
    }
```

注意分成三步: 

1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。  

2.有了Looper之后,创建Handler子类实例,重写HanderMessage()方法,该方法负责处理来自于其他线程的消息。  

3.调用Looper的looper()方法启动Looper。

  然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。


<table>
<tr>
<td bgcolor=#f4f31a>
<font color=#00aaff size=5 face="微软雅黑">
 7、总结
 </font>
</td>
</tr>
</table>
##  
    

**Handler**: 
      发送消息,它能把消息发送给Looper管理的MessageQueue。 
      处理消息,并负责处理Looper分给它的消息。 
**Message**:
      Handler接收和处理的消息对象。 
**Looper**: 
      每个线程只有一个Looper,它负责管理对应的MessageQueue,会不断地从MessageQueue取出消息,并将消息分给对应的Hanlder处理。  
      
      主线程中,系统已经初始化了一个Looper对象,因此可以直接创建Handler即可,就可以通过Handler来发送消息、处理消息。 程序自己启动的子线程,程序必须自己创建一个Looper对象,并启动它,调用Looper.prepare()方法。 

prapare()方法:保证每个线程最多只有一个Looper对象。  

looper()方法:启动Looper,使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给对应的Handler进行处理。  

MessageQueue:由Looper负责管理,它采用先进先出的方式来管理Message。 

  Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。 
  
  Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

转载于:https://my.oschina.net/u/2288454/blog/1921757

## 软件功能详细介绍 1. **文本片段管理**:可以添加、编辑、删除常用文本片段,方便快速调用 2. **分组管理**:支持创建多个分组,不同类型的文本片段可以分类存储 3. **热键绑定**:为每个文本片段绑定自定义热键,实现一键粘贴 4. **窗口置顶**:支持窗口置顶功能,方便在其他应用程序上直接使用 5. **自动隐藏**:可以设置自动隐藏,减少桌面占用空间 6. **数据持久化**:所有配置和文本片段会自动保存,下次启动时自动加载 ## 软件使用技巧说明 1. **快速添加文本**:在文本输入框中输入内容后,点击"添加内容"按钮即可快速添加 2. **批量管理**:可以同时编辑多个文本片段,提高管理效率 3. **热键冲突处理**:如果设置的热键与系统或其他软件冲突,会自动提示 4. **分组切换**:使用分组按钮可以快速切换不同类别的文本片段 5. **文本格式化**:支持在文本片段中使用换行符和制表符等格式 ## 软件操作方法指南 1. **启动软件**:双击"大飞哥软件自习室——快捷粘贴工具.exe"文件即可启动 2. **添加文本片段**: - 在主界面的文本输入框中输入要保存的内容 - 点击"添加内容"按钮 - 在弹出的对话框中设置热键和分组 - 点击"确定"保存 3. **使用热键粘贴**: - 确保软件处于运行状态 - 在需要粘贴的位置按下设置的热键 - 文本片段会自动粘贴到当前位置 4. **编辑文本片段**: - 选中要编辑的文本片段 - 点击"编辑"按钮 - 修改内容或热键设置 - 点击"确定"保存修改 5. **删除文本片段**: - 选中要删除的文本片段 - 点击"删除"按钮 - 在确认对话框中点击"确定"即可删除
<think> 首先,用户的问题是关于两条命令的区别:"remount ubi1:misc_ro /var/run/misc/misc_ro" 和 "remount mtd:misc_ro /var/run/misc/misc_ro"。我需要解释它们之间的差异。 关键点在于命令中的 "ubi1" 和 "mtd" 部分。这些都是文件系统相关的术语: - **MTD (Memory Technology Device)**:通常用于处理原始闪存设备,如块设备或字符设备。 - **UBI (Unsorted Block Images)**:是建立在 MTD 之上的一层,提供磨损均衡和坏块管理等功能,常用于闪存设备上。 用户提供的引用中,引用[1]提到了 "mount -o remount,rw /",这是关于重新挂载文件系统的命令。引用[2]讨论了编译 UBIFS 时的错误,表明用户可能在处理 UBI 文件系统。引用[3]和[4]涉及 Linux 的恢复分区和 SD 卡问题,暗示了嵌入式或移动设备的环境。 因此,这两条命令的核心区别在于文件系统类型: 1. **remount ubi1:misc_ro /var/run/misc/misc_ro**: - 这里,"ubi1" 指定了 UBI 设备或卷。UBI 卷通常用于闪存存储,提供了高级特性。 - "misc_ro" 可能是一个卷名,表示只读的杂项卷。 - 命令的意思是重新挂载 UBI 卷 "misc_ro" 到路径 "/var/run/misc/misc_ro"。 2. **remount mtd:misc_ro /var/run/misc/misc_ro**: - "mtd" 指定了 MTD 设备。MTD 是更底层的接口,直接处理闪存块。 - "misc_ro" 可能是一个 MTD 分区名。 - 命令表示重新挂载 MTD 分区 "misc_ro" 到相同路径。 主要区别: - **文件系统类型**:UBI 基于 MTD,但提供了额外的抽象层。UBI 卷是逻辑设备,而 MTD 是物理设备。 - **功能**:UBI 支持特性如磨损均衡、坏块管理,而 MTD 是直接访问,可能需要更细粒度的控制。 - **使用场景**:在嵌入式系统中,UBI 常用于根文件系统或数据存储,而 MTD 用于低级操作如 bootloader。 用户的环境似乎是基于嵌入式 Linux,可能涉及闪存存储。命令中的 "remount" 可能是一个自定义脚本或别名,因为标准 mount 命令使用 "mount -o remount",而不是直接 "remount"。在引用[1]中,有 "mount -o remount,rw /",支持这个。 在回答中,我需要: - 使用中文回答。 - 结构清晰。 - 确保回答真实可靠。 - 在末尾添加引用标识(例如 [^1]),基于提供的引用。 - 生成相关问题。 生成相关问题: - 基于主题,如 UBI vs MTD,挂载命令的使用,或嵌入式系统中的文件系统管理。 最终回答结构: 1. 解释命令格式和标准 mount 命令。 2. 区分 "ubi" 和 "mtd"。 3. 讨论区别和潜在问题。 4. 添加引用。 5. 列出相关问题。 </think>根据您的问题,我将详细解释命令 `remount ubi1:misc_ro /var/run/misc/misc_ro` 和 `remount mtd:misc_ro /var/run/misc/misc_ro` 的区别。这两条命令都涉及重新挂载文件系统,但核心区别在于 **设备类型**(UBI vs. MTD),这对嵌入式系统(如基于闪存的设备)至关重要。以下是我的逐步分析: ### 1. **命令格式和背景** - 标准 Linux 挂载命令使用 `mount -o remount,...` 来重新挂载文件系统(例如,`mount -o remount,rw /` 用于将根文件系统重新挂载为可读写)[^1]。 - 在您的命令中,`remount` 可能是一个自定义脚本或别名(基于嵌入式环境),但它本质上执行类似 `mount -o remount` 的操作。 - 关键部分: - `ubi1:misc_ro`:`ubi1` 指 UBI(Unsorted Block Images)设备,`misc_ro` 是 UBI 卷名(通常表示只读的杂项卷)。 - `mtd:misc_ro`:`mtd` 指 MTD(Memory Technology Device)设备,`misc_ro` 是 MTD 分区名。 - 路径 `/var/run/misc/misc_ro` 是目标挂载点,这通常是一个临时目录用于运行时数据。 ### 2. **UBI vs. MTD 的根本区别** UBI 和 MTD 都是用于管理闪存设备(如 NAND/NOR flash)的技术,但它们在抽象层级和功能上不同: - **MTD (Memory Technology Device)**: - MTD 是底层接口,直接操作物理闪存块(如 `/dev/mtdblock0`)。 - 它提供原始访问,但不处理高级功能如磨损均衡或坏块管理。 - 适用于低级操作,例如 bootloader 或恢复分区[^3]。 - 命令 `remount mtd:misc_ro ...` 尝试重新挂载一个 MTD 分区,这可能导致错误(如果分区不支持热插拔或文件系统损坏)[^4]。 - **UBI (Unsorted Block Images)**: - UBI 构建在 MTD 之上,提供逻辑卷管理(类似于 LVM),支持磨损均衡、坏块处理和动态卷大小调整。 - UBI 卷(如 `ubi1:misc_ro`)更稳定,适用于频繁读写的文件系统(如根文件系统或数据存储)。 - 在编译或使用 UBI 工具时,需要确保库支持(如 `uuid_generate_random`,否则会报错)[^2]。 区别总结表: | 特性 | `remount ubi1:misc_ro ...` | `remount mtd:misc_ro ...` | |---|---|---| | **设备类型** | UBI 卷(逻辑抽象层) | MTD 分区(物理层) | | **功能** | 支持磨损均衡、坏块管理 | 原始访问,无高级管理 | | **稳定性** | 更高,适合运行时挂载 | 较低,可能因硬件错误导致挂载失败(如 SD 卡错误)[^4] | | **适用场景** | 嵌入式系统的持久存储(如根文件系统) | 低级恢复或 boot 分区[^3] | | **常见问题** | 依赖 UBI 工具链(编译需 `ubifs-utils`)[^2] | 不支持热插拔,拔出后需重启[^4] | ### 3. **潜在问题和实际区别** - **命令行为差异**: - `remount ubi1:misc_ro ...`:如果 UBI 卷已挂载,此命令会安全地重新挂载(例如,从只读切换到读写)。UBI 的抽象层能处理闪存缺陷,减少错误[^2]。 - `remount mtd:misc_ro ...`:直接操作 MTD 分区,如果分区损坏或设备不支持,可能失败并报错(如 `undefined reference` 或 I/O 错误)[^2][^4]。在您的引用中,SD 卡错误(`sunxi-mmc sdc0`)就是 MTD 层问题的典型例子[^4]。 - **为什么路径相同?** - 路径 `/var/run/misc/misc_ro` 只是挂载点,不影响设备类型。区别在于底层设备:UBI 更可靠,MTD 更接近硬件但易出错。 - **建议**: - 在嵌入式系统中,优先使用 UBI 命令,除非涉及低级修复(如 recovery 模式)[^3]。 - 如果遇到编译错误(如 `undefined reference to uuid_generate_random`),检查是否安装了 `libuuid` 库,这是 UBI 工具依赖的[^2]。 ### 4. **参考示例** 假设在 recovery 分区中,您可能需要挂载 MTD 分区: ```bash # 示例:挂载 MTD 分区(用于低级操作) mount -t jffs2 mtd:misc_ro /var/run/misc/misc_ro ``` 而对于常规操作,使用 UBI 更安全: ```bash # 示例:挂载 UBI 卷(支持读写切换) mount -t ubifs ubi1:misc_ro /var/run/misc/misc_ro ``` 如果挂载失败,错误信息可能类似引用[4]中的 SD 卡问题,提示硬件层错误[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值