Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用

关与设备树的概念,我们在Exynos4412 内核移植(六)—— 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用

         Device Tree是一种描述硬件的数据结构,设备树源(Device Tree Source)文件(以.dts结尾)就是用来描述目标板硬件信息的。Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中)。


一、设备树基础概念

1、基本数据格式

      device tree是一个简单的节点和属性树,属性是键值对,节点可以包含属性和子节点。下面是一个.dts格式的简单设备树。

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. / {  
  2.     node1 {  
  3.         a-string-property = "A string";  
  4.         a-string-list-property = "first string""second string";  
  5.         a-byte-data-property = [0x01 0x23 0x34 0x56];  
  6.         child-node1 {  
  7.             first-child-property;  
  8.             second-child-property = <1>;  
  9.             a-string-property = "Hello, world";  
  10.         };  
  11.         child-node2 {  
  12.         };  
  13.     };  
  14.     node2 {  
  15.         an-empty-property;  
  16.         a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */  
  17.         child-node1 {  
  18.         };  
  19.     };  
  20. };  

      该树并未描述任何东西,也不具备任何实际意义,但它却揭示了节点和属性的结构。即:

a -- 一个的根节点:'/',两个子节点:node1和node2;node1的子节点:child-node1和child-node2,一些属性分散在树之间。

b -- 属性是一些简单的键值对(key-value pairs):value可以为空也可以包含任意的字节流。而数据类型并没有编码成数据结构,有一些基本数据表示可以在device tree源文件中表示。

c -- 文本字符串(null 终止)用双引号来表示:string-property = "a string"

d -- “Cells”是由尖括号分隔的32位无符号整数:cell-property = <0xbeef 123 0xabcd1234>

e -- 二进制数据是用方括号分隔:binary-property = [0x01 0x23 0x45 0x67];

f -- 不同格式的数据可以用逗号连接在一起:mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;

g -- 逗号也可以用来创建字符串列表:string-list = "red fish", "blue fish";


二、设备在device tree 中的描述

        系统中的每个设备由device tree的一个节点来表示

1、节点命名

     花些时间谈谈命名习惯是值得的。每个节点都必须有一个<name>[@<unit-address>]格式的名称。<name>是一个简单的ascii字符串,最长为31个字符,总的来说,节点命名是根据它代表什么设备。比如说,一个代表3com以太网适配器的节点应该命名为ethernet,而不是3com509。

    如果节点描述的设备有地址的话,就应该加上unit-address,unit-address通常是用来访问设备的主地址,并在节点的reg属性中被列出。后面我们将谈到reg属性。


2、设备

      接下来将为设备树添加设备节点:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. / {  
  2.     compatible = "acme,coyotes-revenge";  
  3.   
  4.     cpus {  
  5.         cpu@0 {  
  6.             compatible = "arm,cortex-a9";  
  7.         };  
  8.         cpu@1 {  
  9.                     compatible = "arm,cortex-a9";  
  10.             };  
  11.         };  
  12.   
  13.     serial@101F0000 {  
  14.         compatible = "arm,pl011";  
  15.     };  
  16.   
  17.     serial@101F2000 {  
  18.         compatible = "arm,pl011";  
  19.     };  
  20.   
  21.     gpio@101F3000 {  
  22.         compatible = "arm,pl061";  
  23.     };  
  24.   
  25.     interrupt-controller@10140000 {  
  26.         compatible = "arm,pl190";  
  27.     };  
  28.   
  29.     spi@10115000 {  
  30.         compatible = "arm,pl022";  
  31.     };  
  32.       
  33.     external-bus {  
  34.         ethernet@0,0 {  
  35.             compatible = "smc,smc91c111";  
  36.         };  
  37.       
  38.         i2c@1,0 {  
  39.             compatible = "acme,a1234-i2c-bus";  
  40.             rtc@58 {  
  41.                 compatible = "maxim,ds1338";  
  42.             };  
  43.             };  
  44.   
  45.         flash@2,0 {  
  46.             compatible = "samsung,k8f1315ebm""cfi-flash";  
  47.              };  
  48.      };  
  49. };  

        在上面的设备树中,系统中的设备节点已经添加进来,树的层次结构反映了设备如何连到系统中。外部总线上的设备就是外部总线节点的子节点,i2c设备是i2c总线控制节点的子节点。总的来说,层次结构表现的是从CPU视角来看的系统视图。在这里这棵树是依然是无效的。它缺少关于设备之间的连接信息。稍后将添加这些数据。

      设备树中应当注意:每个设备节点有一个compatible属性。flash节点的compatible属性有两个字符串。请阅读下一节以了解更多内容。 之前提到的,节点命名应当反映设备的类型,而不是特定型号。请参考ePAPR规范2.2.2节的通用节点命名,应优先使用这些命名。


3、compatible 属性

      树中的每一个代表了一个设备的节点都要有一个compatible属性。compatible是OS用来决定绑定到设备的设备驱动的关键。

      compatible是字符串的列表。列表中的第一个字符串指定了"<manufacturer>,<model>"格式的节点代表的确切设备,第二个字符串代表了与该设备兼容的其他设备。例如,Freescale MPC8349 SoC有一个串口设备实现了National Semiconductor ns16550寄存器接口。因此MPC8349串口设备的compatible属性为:compatible = "fsl,mpc8349-uart", "ns16550"。在这里,fsl,mpc8349-uart指定了确切的设备,ns16550表明它与National Semiconductor 16550 UART是寄存器级兼容的。

     注:由于历史原因,ns16550没有制造商前缀,所有新的compatible值都应使用制造商的前缀这种做法使得现有的设备驱动程序可以绑定到一个新设备上,同时仍能唯一准确的识别硬件


4、编址

      可编址的设备使用下列属性来将地址信息编码进设备树:

reg

#address-cells

#size-cells

       每个可寻址的设备有一个reg属性,即以下面形式表示的元组列表:

      reg = <address1 length1 [address2 length2] [address3 length3] ... > 

     每个元组,。每个地址值由一个或多个32位整数列表组成,被称做cells。同样地,长度值可以是cells列表,也可以为空。

     既然address和length字段是大小可变的变量,父节点的#address-cells和#size-cells属性用来说明各个子节点有多少个cells。换句话说,正确解释一个子节点的reg属性需要父节点的#address-cells#size-cells值


5、内存映射设备

      与CPU节点中的单一地址值不同,内存映射设备会被分配一个它能响应的地址范围。#size-cells用来说明每个子节点种reg元组的长度大小。

     在下面的示例中,每个地址值是1 cell (32位) ,并且每个的长度值也为1 cell,这在32位系统中是非常典型的。64位计算机可以在设备树中使用2作为#address-cells和#size-cells的值来实现64位寻址。

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. serial@101f2000 {  
  2.     compatible = "arm,pl011";  
  3.     reg = <0x101f2000 0x1000 >;  
  4. };  
  5.   
  6. gpio@101f3000 {  
  7.         compatible = "arm,pl061";  
  8.         reg = <0x101f3000 0x1000  
  9.                0x101f4000 0x0010>;  
  10. };  
  11.   
  12.   
  13. interrupt-controller@10140000 {  
  14.         compatible = "arm,pl190";  
  15.         reg = <0x10140000 0x1000 >;  
  16. };  

      每个设备都被分配了一个基地址及该区域大小。本例中的GPIO设备地址被分成两个地址范围:0x101f3000~0x101f3fff和0x101f4000~0x101f400f。


三、设备树在platform设备驱动开发中的使用解析

         我们仍以 Linux 设备驱动开发 —— platform设备驱动应用实例解析 文中的例子来解析设备树在platform设备驱动中如何使用;

1、设备树对platform中platform_device的替换

         其实我们可以看到,Device Tree 是用来描述设备信息的,每一个设备在设备树中是以节点的形式表现出来;而在上面的 platform 设备中,我们利用platform_device 来描述一个设备,我们可以看一下二者的对比

fs4412-beep{
compatible = "fs4412,beep";
reg = <0x114000a0 0x4 0x139D0000 0x14>;
};

a -- fs4412-beep 为节点名,符合咱们前面提到的节点命名规范;
我们通过名字可以知道,该节点描述的设备是beep, 设备名是fs4412-beep;

b -- compatible = "fs4412,beep"; compatible 属性, 即一个字符串;
      前面提到,所有新的compatible值都应使用制造商的前缀,这里是
fs4412;

c -- reg = <0x114000a0 0x4 0x139D0000 0x14>;
       reg属性来将地址信息编码进设备树,表示该设备的地址范围;这里是我们用到的寄存器及偏移量;
static struct  resource beep_resource[] =
{
[0] = {
.start = 0x114000a0,
.end = 0x114000a0+0x4,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0x139D0000,
.end = 0x139D0000+0x14,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device hello_device=
{
.name = "bigbang",//没用了
.id = -1,
.dev.release = hello_release,
.num_resources = ARRAY_SIZE(beep_resource ),
.resource = beep_resource,
};

      可以看到设备树中的设备节点完全可以替代掉platform_device。


2、有了设备树,如何实现device 与 driver 的匹配?

      我们在上一篇还有 platform_device 中,是利用 .name 来实现device与driver的匹配的,但现在设备树替换掉了device,那我们将如何实现二者的匹配呢?有了设备树后,platform比较的名字存在哪?

     我们先看一下原来是如何匹配的 ,platform_bus_type 下有个match成员,platform_match 定义如下

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static int platform_match(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     struct platform_device *pdev = to_platform_device(dev);  
  4.     struct platform_driver *pdrv = to_platform_driver(drv);  
  5.   
  6.     /* Attempt an OF style match first */  
  7.     if (of_driver_match_device(dev, drv))  
  8.         return 1;  
  9.   
  10.     /* Then try ACPI style match */  
  11.     if (acpi_driver_match_device(dev, drv))  
  12.         return 1;  
  13.   
  14.     /* Then try to match against the id table */  
  15.     if (pdrv->id_table)  
  16.         return platform_match_id(pdrv->id_table, pdev) != NULL;  
  17.   
  18.     /* fall-back to driver name match */  
  19.     return (strcmp(pdev->name, drv->name) == 0);  
  20. }  
其中又调用了of_driver_match_device(dev, drv) ,其定义如下:
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static inline int of_driver_match_device(struct device *dev,  
  2.                      const struct device_driver *drv)  
  3. {  
  4.     return of_match_device(drv->of_match_table, dev) != NULL;  
  5. }  
其调用of_match_device(drv->of_match_table, dev) ,继续追踪下去,注意这里的参数 drv->of_match_table
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. const struct of_device_id *of_match_device(const struct of_device_id *matches,  
  2.                        const struct device *dev)  
  3. {  
  4.     if ((!matches) || (!dev->of_node))  
  5.         return NULL;  
  6.     return of_match_node(matches, dev->of_node);  
  7. }  
  8. EXPORT_SYMBOL(of_match_device);  
又调用 of_match_node(matches, dev->of_node)  ,其中matches 是 struct of_device_id 类型
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * of_match_node - Tell if an device_node has a matching of_match structure 
  3.  *  @matches:   array of of device match structures to search in 
  4.  *  @node:      the of device structure to match against 
  5.  * 
  6.  *  Low level utility function used by device matching. 
  7.  */  
  8. const struct of_device_id *of_match_node(const struct of_device_id *matches,  
  9.                      const struct device_node *node)  
  10. {  
  11.     const struct of_device_id *match;  
  12.     unsigned long flags;  
  13.   
  14.     raw_spin_lock_irqsave(&devtree_lock, flags);  
  15.     match = __of_match_node(matches, node);  
  16.     raw_spin_unlock_irqrestore(&devtree_lock, flags);  
  17.     return match;  
  18. }  
  19. EXPORT_SYMBOL(of_match_node);  
找到 match = __of_match_node(matches, node); 注意着里的node是struct device_node 类型的
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. const struct of_device_id *__of_match_node(const struct of_device_id *matches,  
  2.                        const struct device_node *node)  
  3. {  
  4.     const struct of_device_id *best_match = NULL;  
  5.     int score, best_score = 0;  
  6.   
  7.     if (!matches)  
  8.         return NULL;  
  9.   
  10.     for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {  
  11.         score = __of_device_is_compatible(node, matches->compatible,  
  12.                           matches->type, matches->name);  
  13.         if (score > best_score) {  
  14.             best_match = matches;  
  15.             best_score = score;  
  16.         }  
  17.     }  
  18.   
  19.     return best_match;  
  20. }  
继续追踪下去
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static int __of_device_is_compatible(const struct device_node *device,  
  2.                      const char *compat, const char *type, const char *name)  
  3. {  
  4.     struct property *prop;  
  5.     const char *cp;  
  6.     int index = 0, score = 0;  
  7.   
  8.     /* Compatible match has highest priority */  
  9.     if (compat && compat[0]) {  
  10.         prop = __of_find_property(device, "compatible", NULL);  
  11.         for (cp = of_prop_next_string(prop, NULL); cp;  
  12.              cp = of_prop_next_string(prop, cp), index++) {  
  13.             if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {  
  14.                 score = INT_MAX/2 - (index << 2);  
  15.                 break;  
  16.             }  
  17.         }  
  18.         if (!score)  
  19.             return 0;  
  20.     }  
  21.   
  22.     /* Matching type is better than matching name */  
  23.     if (type && type[0]) {  
  24.         if (!device->type || of_node_cmp(type, device->type))  
  25.             return 0;  
  26.         score += 2;  
  27.     }  
  28.   
  29.     /* Matching name is a bit better than not */  
  30.     if (name && name[0]) {  
  31.         if (!device->name || of_node_cmp(name, device->name))  
  32.             return 0;  
  33.         score++;  
  34.     }  
  35.   
  36.     return score;  
  37. }  
看这句 prop = __of_find_property(device, "compatible", NULL);

可以发先追溯到底,是利用"compatible"来匹配的,即设备树加载之后,内核会自动把设备树节点转换成 platform_device这种格式,同时把名字放到of_node这个地方
   

platform_driver 部分

可以看到原来是利用platform_driver 下的 struct driver 结构体中的 name 成员来匹配的,看一下 struct driver 结构体的定义:
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct device_driver {  
  2.     const char      *name;  
  3.     struct bus_type     *bus;  
  4.   
  5.     struct module       *owner;  
  6.     const char      *mod_name;  /* used for built-in modules */  
  7.   
  8.     bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */  
  9.   
  10.     const struct of_device_id   *of_match_table;  
  11.     const struct acpi_device_id *acpi_match_table;  
  12.   
  13.     int (*probe) (struct device *dev);  
  14.     int (*remove) (struct device *dev);  
  15.     void (*shutdown) (struct device *dev);  
  16.     int (*suspend) (struct device *dev, pm_message_t state);  
  17.     int (*resume) (struct device *dev);  
  18.     const struct attribute_group **groups;  
  19.   
  20.     const struct dev_pm_ops *pm;  
  21.   
  22.     struct driver_private *p;  
  23. }  
      成员中有const struct of_device_id*of_match_table; 是struct of_device_id 类型,定义如下:
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Struct used for matching a device 
  3.  */  
  4. struct of_device_id  
  5. {  
  6.     char    name[32];  
  7.     char    type[32];  
  8.     char    compatible[128];  
  9.     const void *data;  
  10. };  
      可以看到其作用就是为了匹配一个设备。我们所要做的就是对 char compatible[128] 的填充;设备树加载之后,内核会自动把设备树节点转换成 platform_device这种格式,同时把名字放到of_node这个地方。


3、基于设备树的driver的结构体的填充

      匹配的方式发生了改变,那我们的platform_driver 也要修改了

基于设备树的driver的结构体的填充:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static struct of_device_id beep_table[] = {  
  2.     {.compatible = "fs4412,beep"},  
  3. };  
  4. static struct platform_driver beep_driver=  
  5. {  
  6.     .probe = beep_probe,  
  7.     .remove = beep_remove,  
  8.     .driver={  
  9.         .name = "bigbang",  
  10.         .of_match_table = beep_table,  
  11.     },  
  12. };  
原来的driver是这样的,可以对比一下
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static struct platform_driver beep_driver=  
  2. {  
  3.     .driver.name = "bigbang",  
  4.     .probe = beep_probe,  
  5.     .remove = beep_remove,  
  6. };  

4、设备树编译

      我们在 arch/arm/boot/dts/exynos4412-fs4412.dts 中添加

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. fs4412-beep{  
  2.          compatible = "fs4412,beep";  
  3.          reg = <0x114000a0 0x4 0x139D0000 0x14>;  
  4. };  

就可以编译设备树了

make dtbs  在内核根目录
vim arch/arm/boot/dts/exynos4412-fs4412.dts
sudo cp  arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/

     然后,将设备树下载到0x42000000处,并加载驱动 insmod driver.ko, 测试下驱动。

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

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

相关文章

Android 网络通信框架Volley简介(Google IO 2013)

1. 什么是Volley 在这之前&#xff0c;我们在程序中需要和网络通信的时候&#xff0c;大体使用的东西莫过于AsyncTaskLoader&#xff0c;HttpURLConnection&#xff0c;AsyncTask&#xff0c;HTTPClient&#xff08;Apache&#xff09;等&#xff0c;今年的Google I/O 2013上&…

Linux 设备驱动开发 —— platform设备驱动应用实例解析

前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 —— platform 设备驱动 &#xff0c;下面将通过一个实例来深入我们的学习。 一、platform 驱动的工作过程 platform模型驱动编程&#xff0c;需要实现platform_device(设备)与platform_driver&#xff08;驱动&am…

Python爬虫入门四urllib库的高级用法

1.设置headers 有些网站不会同意程序直接用上面的方式进行访问&#xff0c;如果识别有问题&#xff0c;那么站点根本不会响应&#xff0c;所以为了完全模拟浏览器的工作&#xff0c;我们需要设置一些 Headers 的属性。 首先&#xff0c;打开我们的浏览器&#xff0c;调试浏览器…

进程上下文、中断上下文及原子上下文

谈论进程上下文 、中断上下文 、 原子上下文之前&#xff0c;有必要讨论下两个概念&#xff1a; a -- 上下文 上下文是从英文context翻译过来&#xff0c;指的是一种环境。相对于进程而言&#xff0c;就是进程执行时的环境&#xff1b; 具体来说就是各个变量和数据&#xff0c;…

Linux 文件系统与设备文件系统 (二)—— sysfs 文件系统与Linux设备模型

提到 sysfs 文件系统 &#xff0c;必须先需要了解的是Linux设备模型&#xff0c;什么是Linux设备模型呢&#xff1f; 一、Linux 设备模型 1、设备模型概述 从2.6版本开始&#xff0c;Linux开发团队便为内核建立起一个统一的设备模型。在以前的内核中没有独立的数据结构用来让内…

Python爬虫入门七正则表达式

已经搞定了怎样获取页面的内容&#xff0c;不过还差一步&#xff0c;这么多杂乱的代码夹杂文字我们怎样把它提取出来整理呢&#xff1f;下面就开始介绍一个十分强大的工具&#xff0c;正则表达式 1.了解正则表达式 正则表达式是用来匹配字符串非常强大的工具&#xff0c;在其…

Linux 文件系统与设备文件系统 (一)—— udev 设备文件系统

一、什么是Linux设备文件系统 首先我们不看定义&#xff0c;定义总是太抽象很难理解&#xff0c;我们先看现象。当我们往开发板上移植了一个新的文件系统之后&#xff08;假如各种设备驱动也移植好了&#xff09;&#xff0c;启动开发板&#xff0c;我们用串口工具进入开发板&a…

情人节,教大家使用css画出一朵玫瑰花。

情人节到了&#xff0c;给大家来一朵高端的玫瑰花。 在网上看到的一个canvas实现的玫瑰花&#xff0c;效果很好&#xff0c;但是代码被压缩过&#xff0c;也没有注释&#xff0c;看的云里雾里的。 今天我教大脚用CSS来实现一朵玫瑰花。 先看效果 首先我们画出一个花瓣 1、画出一…

Linux 字符设备驱动开发基础(六)—— VFS 虚拟文件系统解析

一、VFS 虚拟文件系统基础概念 Linux 允许众多不同的文件系统共存&#xff0c;并支持跨文件系统的文件操作&#xff0c;这是因为有虚拟文件系统的存在。虚拟文件系统&#xff0c;即VFS&#xff08;Virtual File System&#xff09;是 Linux 内核中的一个软件抽象层。它通过一些…

vim使用—实现程序的自动补齐(C语言)

使用过Source Insight的人一定对它的自动补全功能印象深刻&#xff0c;在很多的集成开发环境中&#xff0c;也都支持自动补全。vim做为一个出色的编辑器&#xff0c;这样的功能当然少不了。至于如何实现程序自动补全&#xff0c;网上教程很多。这里&#xff0c;我将自己配置过程…

[C#]Attribute特性(3)——AttributeUsage特性和特性标识符

相关文章 [C#]Attribute特性 [C#]Attribute特性(2)——方法的特性及特性参数 AttributeUsage特性 除了可以定制自己的特性来注释常用的C#类型外&#xff0c;您可以用AttributeUsage特性来定义您想怎样使用这些特性。AttributeUsage特性采用如下的调用惯例&#xff1a; 1 [Attri…

Linux 命令 ——less命令

less 工具也是对文件或其它输出进行分页显示的工具&#xff0c;应该说是linux正统查看文件内容的工具&#xff0c;功能极其强大。less 的用法比起 more 更加的有弹性。在 more 的时候&#xff0c;我们并没有办法向前面翻&#xff0c; 只能往后面看&#xff0c;但若使用了 less …

android闹钟实现原理

闹钟的原理可用下面我自己画的一幅图来概括&#xff1a;&#xff08;不对的地方&#xff0c;尽管吐槽&#xff09; 我们来看看新建闹钟到闹钟响铃的步骤&#xff1a; 1、新建一个闹钟&#xff1a; ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22…

将openstack的Token认证信息存储在memcache中

公司线上的openstack环境运行了5个多月的时间&#xff0c;keystone库的token表已经增长到了31GB&#xff0c;这个数据量还是很大的&#xff0c;对于以后的数据库备份很不方便。每次管理openstack的时候&#xff0c;都会产生一个新的token验证&#xff0c;而历史token信息其实都…

Linux 下shell编程

什么是shell?Shell是一个命令解析器&#xff0c;是介于Linux操作系统的内核(kernel)与用户之间的一个绝缘层。shell脚本就是讲各类命令预先放入其中&#xff0c;方便一次性执行的一个程序文件&#xff0c;主要用于方便管理员进行设置或者管理。 序员的角度来看&#xff0c; Sh…

linux 目录/sys 解析

今天学习Linux目录时&#xff0c;遇到/sys这个目录&#xff0c;老师怎么讲的&#xff0c;不太清楚&#xff0c;先对/sys目录知识进行一个整理 首先&#xff0c;对 /sys目录下的各个子目录进行具体说明&#xff1a; /sys下的子目录 内容 /sys/devices 该目录下…

南下事业篇——深圳 深圳(回顾)

2019独角兽企业重金招聘Python工程师标准>>> 二0一二年三月二十三号记录了下面的一篇日志&#xff0c;现在回味一下觉得自己有点惭愧&#xff0c;但不后悔&#xff0c;知道的越多就越了解自己的无知&#xff0c;工作之后渐渐磨灭了许多锐气&#xff0c;变得平滑低调…

php中花括号的使用

一、界定变量名 注&#xff1a;花括号内若左侧出现空格&#xff0c;则会当做普通花括号来解析。 二、界定表达式 1.获取字符串中某个字符 如&#xff1a;$strabcdefg; echo $str{0};//a 效果等同于$str[0]; 2.作为表示下标的方法定义数组 如&#xff1a;$arr []; $arr{10}4;…

游戏开发--开源软件8--cyclone2D(手机引擎+设计工具)

2019独角兽企业重金招聘Python工程师标准>>> Cyclone2D (飓风软件)是集成的手机游戏设计工具以及开源的引擎&#xff0c;工具提供了强大的动画、地图、数值、脚本等设计功能&#xff0c;开源引擎提供了一体化的模块加载与管理&#xff0c;并提供了详细的API文档以及…

python编码

https://www.cnblogs.com/xiao-xue-di/p/11283496.html 《Python中的Unicode编码和UTF-8编码》 《字符串和编码》 《python编码转换(unicode / utf8 / gbk / 内部编码)》 字符编码 最早127个字母被编码到计算机里&#xff0c;也就是大小写英文字母、数字和一些符号&#xff0…