mknod - make block or character special files
mknod [OPTION]... NAME TYPE [MAJOR MINOR]
option 有用的就是 -m 了
name 自定义
type 有 b 和 c 还有 p
主设备号
次设备号
主设备号是由linux/major.h定义的,如下定义了一个DOC设备:
#define IGEL_FLASH_MAJOR 62
假如有一个命令mknod doc b 62 0 :
其中的doc为定义的名字,b指块设备,0指的是整个DOC。如果把0换为1,则1指的是DOC的第一个分区。2是第2个,对于块设备次设备号就表示该块设备上的分区号,依次类推。
至于mknod console c 5 1 的意思也很相似:
console是设备的名字
c指字符设备
5是该设备在major.h中定义的标记
1是第一个子设备
mknod console c 5 1
console为设备文件名,自己随便取
c是指字符型设备 (可选b,块设备)
5是主设备号 /dev/devices里面记录现有的设备
找个没有用的就可以了
1是次设备号,当你要给两个同样的设备上一个驱动的时候就要分了,从0开始,1就是第二个了 ,对于字符设备,次设备号就表示同类型设备的不同设备。
通常情况下,安装系统时已经创建了常用的设备文件,可以直接访问这些设备文件来访问设备。但在用户重新定制内核,并添加了新硬件驱动程序之后,新驱动程序对应的设备文件就可能不存在。在FreeBSD中,最常见的例子就是在内核中增加声卡的驱动程序时,就需要创建相应设备文件。
创建设备文件的基本方式是使用mknod,但是必须知道该设备的正确设备号才可以。另一种简单的方式是使用/dev目录下的shell程序 MAKEDEV来完成,MAKEDEV实质上就是记录了很多设备的名字与其设备号之间的关系的程序,因此它能使用正确的设备号来创建设备。首先进入 /dev目录,然后再执行MAKEDEV。
# cd /dev
# sh MAKEDEV snd0
MAKEDEV将使用设备名作参数创建设备文件,同时也创建这个设备文件依赖的其他相关设备文件。MAKEDEV的参数,并不一定为创建的设备文件名。例如建立 “MAKEDEV vty8” 将建立ttyv0到ttyv7共8个设备文件,使用 “MAKEDEV wd1s1a” 命令,将建立 wd1、wd1s1、wd1s2等,以及wd1s1a、wd1s1b等设备文件。也可以使用all做MAKEDEV的参数,这将首先清除/dev目录下的所有设备文件,然后MAKEDEV创建所有预设的设备文件。一般情况下这将创建足够多的设备文件,其中的大部分设备文件在具体的系统中不会用得到。
如果对一个系统中没有(或者即使有但内核没有支持或探测到)的设备对应的设备文件进行操作,则系统返回Device not configured的错误信息。
MAKEDEV将使用mknod和对应设备的正确参数,包括字符或块设备、主设备号和从设备号来建立相应的设备文件。管理员也可以直接使用 mknod创建设备文件,但这就必须将这些设备参数统统指定正确才行。因此除非对系统中的硬件驱动程序特别熟悉,一般不直接使用mknod来创建设备文件。
1.创建资源包:
public class Sript_01 : MonoBehaviour
{
[MenuItem ("自定义资源包/创建资源包")]
static void ExecCreateAssetBunldes()
{
//设置保存资源包的根路径
string targetDir = Application.dataPath + "/AssetBundles";
Object[] SelectedAsset = Selection.GetFiltered(typeof (Object),SelectionMode.DeepAssets);
//创建一个目录,用于保存资源包
if(!Eirectory.Exists(targetDir))
{
Directory.CreateDirectory(targetDir);
}
for(int i=0;i<selectedAsset.Length;i++)
{
//生成资源包的完整路径
string filepath = targetDir + "/" + SelectedAsset[i].name + ".unity3d";
//根据路径判断资源包文件是否存在
if(File.Exists(filePath))
{
File.Delete(filePath);
}
//生成新的资源包文件
if(BuildPipeline.BuildAssetBundle(SelectedAsset[i],null,filePath,BuildAssetBundleOptions.CollectDependencies))
{
Debug.Log(“资源包生成成功”);
AssetDatabase.Refresh();
}
else
Debug.Log("资源包文件生成失败");
}
}
}
}
Note: This is an editor class. To use it you have to place your script in Assets/Editor inside your project folder. Editor classes are in the UnityEditor namespace so for C# scripts you need to add "using UnityEditor;" at the beginning of the script.
2.下载资源包
IEnumerator loadBundleMat(string name)
{
Material mat;
//资源在本机的路径
WWW date = new WWW("file://" + Application.dataPath + "/AssetBundles/" + name + "./unity3d");
//等待下载完成
yield return date;
//将下载得到的资源强制转换成材质资源
mat = (Material)date.assetBundle.mainAsset;
//更换为下载的资源
renderer.material = mat;
//释放资源对象
date.assetBundle.Unload(false);
}
IEnumerator loadBundleObject (string name)
{
WWW date = new WWW("file://" + Application.dataPath + "AssetBundles/" + name + ".unity3d");
//等待下载完成,并且克隆游戏对象,
yield return Instantiate(date.assetbundle.mainAsset);
//释放资源对象
date.assetbundle.Unload(false);
}
注释: 资源包下载完成后,资源文件将保持在assetBundle.mainAsset 对象中,接着使用该对象即可。由于连续下载资源包对象会出错,所以下载完资源后需要手动释放对象。
创建屏幕控件----App Widget
Android SDK给开发人员提供了可以在移动应用程序的传统边界外面提供功能,这就是App Widget。开发人员可使用App Widget API创建可加入到主屏幕中的小型控件。这些控件简单但功能强大,可向用户提供有关应用程序的补充信息,并提醒用户在必要时启动应用程序。
对有些类型的应用程序(如需要将状态或更新告知用户的应用程序)来说,App Widget很有用。天气应用程序可能包含这样的App Widget,即显示指定地区的当前天气状况;任务管理应用程序可能包含这样的App Widget,即告诉用户其待办事项中的下一个事项是什么以及当前还有多少个事项要办;图库应用程序可能包含这样的App Widget,即以幻灯片的方式列出图库中所有的图片。
要实现简单的App Widget,必须利用前面学习的很多技能。创建App Widget的步骤如下:
1、 创建App Widget配置文件;
2、创建App Widget布局资源文件;
3、实现App Widget提供器;
4、 实现Android服务,在必要时更新App Widget;
5、 在Android清单文件中注册App Widget和相关的服务。
下面我们来更详细地学习每个步骤:
1、配置App Widget的属性
必须在一个独立的XML文件中指定App Widget的定义和配置属性,然后在Android清单文件中引用他们。下面是一些用于定义App Widget的常见属性:
大小:App Widget的宽度和高度,以独立于密度的像素(dp或dip)为单位,它对应于正确显示App Widget需要的主屏幕网格单元数。Android主屏幕被划分成网格单元格,每个单元格为74×74像素。在每个单元格中,只能有一项内容,如App Widget或应用程序快捷方式,这可确保各项内容不会重叠。
更新频率:系统两次调用App Widget提供器来更新App Widget的内容之间相隔的时间,单位为毫秒。
初始布局:最初添加App Widget时使用的布局文件,以后可使用代码对初始布局进行修改。
配置活动:首次显示App Widget前将启动的活动,该活动将配置App Widget的各个方面。
首先在资源文件夹/res/xml中添加一个名为example_appwidget_info.xml的XML文件:
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="60dp" android:minHeight="30dp" android:updatePeriodMillis="10000" android:initialLayout="@layout/example_appwidget" > </appwidget-provider>
注意,Google给了这样一个说明:
public int updatePeriodMillis
Since: API Level 3
How often, in milliseconds, that this AppWidget wants to be updated. The AppWidget manager may place a limit on how often a AppWidget is updated.
This field corresponds to the android:updatePeriodMillis attribute in the AppWidget meta-data file.
Note: Updates requested with updatePeriodMillis will not be delivered more than once every 30 minutes.
这说明android:updatePeriodMillis="1080000"App Widget最短更新间隔为30分钟,所以updatePeriodMillis如果设置小于30分钟,App Widget将默认30分钟执行一次。
这个文件定义了一个App Widget,它每隔3小时更新一次,大小为4×2个单元格。如果您进行计算就会发现我们定义的宽和高不是前面定义的网格单元格大小74dp的整数倍,原因是虽然通常认为网个单元格大小为74dp,但计算App Widget的大小时,必须将最终结果减去2,例如74×2 = 148,减去2后为146。如果不这样做,App Widget占据的单元格数可能不符合预期。
另外,这个App Widget最初使用一个预定义布局,这是使用android:initialLayout = “@layout/widget”指定的。下面我们创建这个布局,它表示App Widget的用户界面。
2、创建App Widget布局资源文件
App Widget有独特的布局要求。首先App Widget是通过接口RemoteViews绘制的,这限制了可显示的用户界面控件的类型;其次App Widget必须与其定义中配置的大小一致。当视图由另一个进程显示时,将使用RemoteViews对象。App Widget正是这样的,他是在App Widget宿主进程而不是在应用程序主进程中显示的。RemoteViews对象可以使用的布局和视图对象收到了限制,下面是可以再App Widget中使用的布局和视图对象:
LinearLayout;
FrameLayout;
RelativeLayout;
TextView;
ImageView;
Button;
ImageButton;
ProgressBar;
AnalogClock;
Chronometet。
不能使用这些控件的子类,这意味着布局的设计受到限制。一种改善App Widget功能的典型的方式是,在需要更强大的功能或更复杂的屏幕时启动一个应用程序活动。
下面我们开始设计App Widget的布局,创建一个布局文件/res/layout/example_appwidget.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/widgetTextId" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="firstWidgetText" android:background="#000000"/> </LinearLayout>
3、实现App Widget提供器
使用AppWidgetProvider类必须通过在清单文件中使用<receiver>元素来声明它,实现为一个广播接收器。
AppWidgetProvider类扩展BroadcastReceiver为一个简便类来处理App Widget广播。AppWidgetProvider只接收和这个AppWidget相关的事件广播,比如这个App Widget被更新,删除,启用,以及禁用。当这些广播事件发生时,AppWidgetProvider将接收到下面的方法调用;
onUpdate(Context , AppWidgetManager , int[])
这个方法用来间隔性的更新App Widget,间隔时间用AppWidgetProviderInfo里的updatePeriodMillis属性定义。这个方法也会在用户添加App Widget时被调用,因此它应该执行基础的设置,比如视图定义事件处理器并启动一个临时的服务Service。但是如果你已经声明了一个配置活动,这个方法在用户添加App Widget时将不会被调用,而只在后续更新是被调用。配置活动应该在配置完成时负责执行一次更新;
onDeleted(Context , int[])
当App Widget从宿主中删除是被调用;
onEnabled(Context)
当一个App Widget实例第一次创建时被调用。比如,如果用户添加两个你的App Widget实例,只在第一次被调用。如果你需要打开一个新的数据库或者执行其他对于所有的App Widget实例只需要发生一次的设置,那么这里是完成这个工作的好地方。
onDisabled(Context)
当你的App Widget的最后一个实例被从宿主中国删除时被调用。你应该在onEnabled(Context)中做一些清理工作,比如删除一个临时的数据库。
onReceive(Context , Intent)
当接收到每个广播时都会被调用,而且在上面的回调函数之前。你通常不需要实现这个方法,因为缺省的AppWidgetProvider实现过滤所有App Widget广播并恰当的调用上述方法。
最重要的AppWidgetProvider回调函数是onUpdated(),因为它是在每个App Widget添加进宿主时被调用的(除非你使用一个配置活动)。如果你的App Widget要接受任何用户交互事件,那么你需要在这个回调函数中注册时间处理器。如果你的App Widget不创建临时文件或数据库,或者不执行其他需要清理的工作,那么onUpdated()可能是你需要定义的唯一的回调函数。比如你想要一个带按钮的App Widget,当点击时启动一个活动,你可以使用下面的AppWidgetProvider实现:
package com.example.test04; import java.util.Calendar; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.RemoteViews; public class ExampleAppWidgetProvider extends AppWidgetProvider { @Override public void onEnabled(Context context) { super.onEnabled(context); Log.i("输出", "onEnabled...正在执行"); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.i("输出", "onUpdate...正在执行"); super.onUpdate(context, appWidgetManager, appWidgetIds); Log.i("输出", "onUpdate...正在执行"); } @Override public void onDisabled(Context context) { super.onDisabled(context); Log.i("输出", "onDisabled...正在执行"); } @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); Log.i("输出", "onDeleted...正在执行"); } @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); Log.i("输出", "onReceive...正在执行"); }
这个AppWidgetProvider仅定义了onUpdate()方法,为了定义一个PendingIntent,来启动一个活动并使用setOnClickPendingIntent(int , PendingIntent)方法把他附着到这个AppWidget的按钮上。注意它包含了一个遍历appWidgetIds中所有项的循环,这是一个Ids数组,每个ID用来标识由这个Provider创建的一个App Widget。这样,如果创建多余一个这个App Widget的实例,那么它们将被同步更新。不过,对于所有的App
Widget实例,只有一个updatePeriodMillis时间表被管理。比如,如果这个更新时间表被定义为每隔两个小时,而且App Widget的第二个是在第一个后面一小时添加的,那么它们将按照第一个所定义的周期来更新而第二个被忽略。
注意:因为这个AppWidgetProvider是一个广播接收器BroadcastReceiver,不能保证你的进程在回调函数返回后仍然继续。
4、处理App Widget后台任务
对于持续时间很长的操作,常规的是以异步方式执行它们。然后,对于App Widget,这种不可行,因为没有管理这种任务的底层活动。App Widget所属的进程随时可能终止,即使正在执行异步任务。因此,必须创建一个Android Service对象,并在服务中执行所需的后台操作。
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.i("输出", "onUpdate...正在执行"); updateAppWidget(context, appWidgetManager , appWidgetIds); super.onUpdate(context, appWidgetManager, appWidgetIds); Log.i("输出", "onUpdate...正在执行"); } public static void updateAppWidget(Context context , AppWidgetManager appWidgetManager , int[] appWidgetIds) { RemoteViews remoteViews = new RemoteViews(context.getPackageName() , R.layout.example_appwidget); remoteViews.setTextViewText(R.id.widgetTextId, Calendar.getInstance().getTime() + ""); Log.i("输出", Calendar.getInstance().getTime() + ""); appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); }
5、在Android清单文件中注册App Widget和相关的服务
<receiver android:name="com.example.test04.ExampleAppWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/example_appwidget_info"> </meta-data> </receiver>