linux

linux

安装软件

dpkg -i ***.deb

chmod

chmod a+x * 对所有文件赋予可执行权限

chmod -R 777 * 赋予可修改权限(包含子文件夹)

cat/vi/less/gedit

cat命令功能用于显示整个文件的内容

    cat <<EOF (允许多行输入,直到遇见“EOF”字串才结束)

more命令功能:让画面在显示满一页时暂停,此时可按空格健继续显示下一个画面,或按Q键停止显示。

less命令除了可以按空格键向下显示文件外,还可以利用上下键来卷动文件。当要结束浏览时,只要在less命令的提示符“: ”下按Q键即可。

 

命令行模式:在一般模式中,输入“: 或者/或者?”,即可将光标移动到最下面一行

一般模式下  /word :  从光标开始,向下查询一个名为word的字符串

Vi按键问题

在vi命令行使用命令“:set nocompatible”,就是设置vi不使用兼容模式。

或 安装vim full版本,在full版本下键盘正常,安装好后同样使用vi命令。

  1. $sudo apt-get remove vim-common
  2. $sudo apt-get install vim

查找

which       查看可执行文件的位置
whereis    查看文件的位置
locate       配合数据库查看文件位置
find          实际搜寻硬盘查询文件名称

find [起始目录] 寻找条件 操作

find –name ’tmp’ –xtype c -user ’inin’

在特定文件类型中查找字符:

find . -name *.xx|xargs grep XXX|grep –v xxxxx   (-v 是过滤后面的字符)

Grep

$ ls -l | grep '^a'
    通过管道过滤ls -l输出的内容,只显示以a开头的行。管道还可以用来这是过滤条件

$ grep 'test' d*
    显示所有以d开头的文件中包含test的行。
$ grep 'test' aa bb cc
    显示在aa,bb,cc文件中匹配test的行。

 

Grep –nr XXX ./

 

-x:全字匹配

 

RE 字符

意义与范例

^word

待搜寻的字串(word)在行首!

范例∶grep -n '^#' regular_express.txt
搜寻行首为 # 开始的那一行!

word$

待搜寻的字串(word)在行尾!

范例∶grep -n '!$' regular_express.txt
将行尾为 ! 的那一行列印出来!

.

代表『任意一个』字符,一定是一个任意字符!

范例∶grep -n 'e.e' regular_express.txt
搜寻的字串可以是 (eve) (eae) (eee) (e e), 但不能仅有 (ee) !亦即 e 与 e 中间『一定』仅有一个字元,而空白字元也是字元!

\

跳脱字符,将特殊符号的特殊意义去除!

范例∶grep -n \' regular_express.txt
搜寻含有单引号 ' 的那一行!

*

重复零个或多个的前一个 RE 字符

范例∶grep -n 'ess*' regular_express.txt
找出含有 (es) (ess) (esss) 等等的字串,注意,因为 * 可以是 0 个,所以 es 也是符合带搜寻字串。另外,因为 * 为重复『前一个 RE 字符』的符号, 因此,在 * 之前必须要紧接著一个 RE 字符喔!例如任意字元则为 『.*』 !

\{n,m\}

连续 n 到 m 个的『前一个 RE 字符』
若为 \{n\} 则是连续 n 个的前一个 RE 字符,
若是 \{n,\} 则是连续 n 个以上的前一个 RE 字符!

范例∶grep -n 'go\{2,3\}g' regular_express.txt
在 g 与 g 之间有 2 个到 3 个的 o 存在的字串,亦即 (goog)(gooog)

[]

字元集合的 RE 特殊字符的符号

[list]
范例∶grep -n 'g[ld]' regular_express.txt
搜寻含有 (gl) 或 (gd) 的那一行~
需要特别留意的是,在 [] 当中『谨代表一个待搜寻的字元』,
例如∶ a[afl]y 代表搜寻的字串可以是 aay, afy, aly
亦即 [afl] 代表 a 或 f 或 l 的意思!

[ch1-ch2]
范例∶grep -n '[0-9]' regular_express.txt
搜寻含有任意数字的那一行!需特别留意,在字元集合 [] 中的减号 - 是有特殊意义的,他代表两个字元之间的所有连续字元!但这个连续与否与 ASCII 编码有关, 因此,您的编码需要设定正确(在 bash 当中,需要确定 LANG 与 LANGUAGE 的变数是否正确!) 例如所有大写字元则为 [A-Z]

[^]
范例∶grep -n 'oo[^t]' regular_express.txt
搜寻的字串可以是 (oog) (ood) 但不能是 (oot) ,那个 ^ 在 [] 内时, 代表的意义是『反向选择』的意思~例如,我不要大写字元,则为 [^A-Z] ~ 但是,需要特别注意的是,如果以 grep -n [^A-Z] regular_express.txt 来搜寻, 却发现该档案内的所有行都被列出,为什么?因为这个 [^A-Z] 是『非大写字元』的意思, 因为每一行均有非大写字元,例如第一行的 "Open Source" 就有 p,e,n,o.... 等等的小写字元, 以及双引号 (") 等字元,所以当然符合 [^A-Z] 的搜寻!

Shell

$n

$1 表示第一个参数,$2 表示第二个参数 …

 

$#

命令行参数的个数

 

$0

当前程序的名称

 

$?

前一个命令或函数的返回码

 

$*

以”参数1 参数2 … ” 形式保存所有参数

 

$@

以”参数1″ “参数2″ … 形式保存所有参数

 

$

本程序的(进程ID号)PID

 

$!

上一个命令的PID

Rfkill,无线开关

关闭无线:sudo rfkill block wifi

打开无线:sudo rfkill unblock wifi

Ifconfig,接口查询和开关

运行不带任何参数的ifconfig命令将显示机器所有激活接口的信息。带有“-a”参数的命令则显示所有接口的信息,包括没有激活的接口。注意,用ifconfig命令配置的网络设备参数,机器重新启动以后将会丢失。

Interface:
指定显示或更改的网络接口配置值。在使用 ifconfig 命令时,必须用 Interface 参数指定接口。接口缩写包括:

at 指 ATM(异步传输方式)
en 指标准以太网(inet,xns)
et 指 IEEE 802.3 以太网(inet,xns)
tr 指令牌环(inet,xns)
xt 指 X.25(inet)
sl 指串行线路 IP(inet)
lo 指回送(inet)
op 指串行(inet)
vi 指虚拟 IP 地址(inet)

down:将接口标记为不活动  up:将接口标记为活动

例:#ifconfig eth0 down

Iwconfig,参数配置

#iwconfig eth0 nickname "My Linux Node"

Mode,设置无线网卡的工作模式,可以是

Ad-hoc:不带AP的点对点无线网络

Managed:通过多个AP组成的网络,无线设备可以在这个网络中漫游

Master:设置该无线网卡为一个AP

Repeater:设置为无线网络中继设备,可以转发网络包

Secondary:设置为备份的AP/Repeater

Monitor:监听模式

Auto:由无线网卡自动选择工作模式

freq/channel,设置无线网卡的工作频率或者频道,小于1000的参数被认为是频道,大于10000的参数被认为是频率。

进程间通信(IPC)

一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。

  • 半双工Unix管道
  • FIFO(命名管道)
  • 消息队列
  • 信号量
  • 共享内存

最快的IPC形式。同一块内存被映射到A,B各自的进程地址空间。进程A可以看到进程B对共享数据的更新,反之亦然。

Android的Binder本质上使用的也是共享内存来通信。使用Binder作为中介,数据会被驱动从进程A中拷贝到Binder和进程B之间的共享内存,即利用IPC设备(作为一个特殊的字符型设备而存在的,设备节点为/dev/binder)。该设备的驱动中申请并使用了共享内存。对共享内存访问的同步控制必须由程序员来负责。

binder设备驱动会为每个进程分配一个数据结构binder_proc,进程中的每个用到了binder通信的线程分配数据结构binder_thread。当把注册服务的请求发给ServiceManager时,ServiceManager也是服务对象的一个引用者,驱动会为ServiceManager增加一个binder_ref,指向服务对象的binder_node。

我们平常使用的共享内存是两个进程之间,即点到点的,如果有N个进程要两两通信而又不相互干扰,那么就必须有N*N个共享内存。Binder使用的共享内存是进程与binder设备之间,即binder做为一个中间者进行传递。进程A向进程B传递数据时,数据会被驱动从进程A中拷贝到binder和进程B之间的共享内存中,然后进程B就可以直接读了。

 

AIDL用的就是共享内存技术。

public static abstract class Stub extends android.os.Binder implements XXX

Stub类就是继承于Binder类,也就是说RemoteService类和普通的Service类没什么不同,只是所返回的IBinder对象比较特别,是一个实现了AIDL接口的Binder。

  • 网络socket

利用设备的固定性,解决了不同进程内存映射不同产生的数据通信问题。

1,通过本地回环接口(即LoopBack)127.0.0.1来收发数据;2,通过文件作为收发数据的中转站;3,在内存中开辟一块区域作为收发数据的中转站,此区域仍然使用文件读写API进行访问。LocalSocket支持方式2和方式3,从效率的角度来说,显然是方式3效率最高

Pipe

  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
  • 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
  • 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
  • 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

OS使用设备

设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:
  1、对设备初始化和释放;
  2、把数据从内核传送到硬件和从硬件读取数据;
  3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据;
  4、检测和处理设备出现的错误。

 

发现硬件:硬件上电后,会向OS发送数据,其中就包括设备自身的设备名及型号等相关参数。驱动文件放在os的特定文件夹下,开机后回去调用。

 

用户程序--(printf)---OS----设备驱动程序--(input)---设备--(output)--OS---用户程序

 

x86系统为控制设备设置了一个地址空间,这个空间称为计算机的I/O端口空间,这个空间占据了65536个8位的范围。

不同的处理器对设备控制接口有不同的访问方式。对x86系统来说,专门提供了特别的指令来访问设备寄存器。这就是x86系统的I/O指令。

需要把设备的寄存器基址纳入到系统的I/O端口空间里面,然后就可以通过系统提供的I/O指令来访问设备的寄存器。假设设备厂商提供的寄存器基址是0x1c00,长度是8字节。有两种情况:

一种是0x1c00地址和别的设备没有冲突,可以直接使用,操作系统内核就记录设备的寄存器基址为0x1c00,驱动通过x86系统提供的I/O指令访问I/O地址0x1c00,或者叫0x1c00 I/O端口,就可以设置设备输入寄存器的内容。通过I/O指令访问地址0x1c04,就可以读到设备输出寄存器的内容。

另外一种情况是其他设备使用了0x1c00这个I/O地址。操作系统内核就需要寻找一个合适的寄存器基址,然后更新设备的寄存器基址,并记录到内核的设备信息里面。驱动使用x86的I/O指令访问这个更新后的地址,就可以设置设备输入寄存器的内容了。

通过设备的I/O端口控制设备,这就是设备驱动的功能。设备厂商会提供设备寄存器的详细内容,这也是驱动开发者所必须关注的。而发现设备、扫描设备信息、为设备提供合适的I/O地址空间,这是内核的总线部分要处理的事情。

访问设备的内存和前面的过程有所不同。因为设备内存不占用I/O端口空间,而是和系统内存占据一样的地址空间。内核读取设备内存基址,然后需要找到合适的内存空间,把设备的内存映射到内存空间。这样驱动就可以用标准的内存接口访问设备的内存了。

 

MMU启动前程序中的地址为物理地址,和硬件手册中规定的地址一致。MMU启动后程序中的地址为虚拟地址,参照MMU地址映射表

System方法

framework/base/cmds目录下有不少目录,这些目录里的可执行文件最终都是放到/system/bin目录下,而源码则变成成jar放在system\framework里。

调用system,通过shell,执行可执行程序或者脚本am。system()函数调用/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell,比如bash,-c选项是告诉shell从字符串command中读取命令;

 

例,系统广播:

system("am broadcast -a com.samsung.slsi.telephony.dmsettings.ZIP_ACTION -n com.samsung.slsi.telephony.dmsettings/.DMSettingsReceiver");

system("/system/bin/sh -c \"am broadcast -a android.intent.action.AT_AIRPLANE_MODE --ez state true\"");

system()函数执行了三步操作:

    a.fork一个子进程;

    b.在子进程中调用exec函数去执行command;

    c.在父进程中调用wait去等待子进程结束。

    对于fork失败,system()函数返回-1。

  如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值。

  注意,command顺利执行不代表执行成功,比如command:"rm debuglog.txt",不管文件存不存在该command都顺利执行了

Am

am的代码实现在\frameworks\base\cmds\am\目录下:

public class Am extends BaseCommand {

//拥有main,可以独立启动运行

    public static void main(String[] args) {

        (new Am()).run(args);   //run方法在基类中,会调用onRun

}

 

    @Override

public void onRun() throws Exception {

    mAm = ActivityManagerNative.getDefault();

if (op.equals("broadcast ")) {

 

mAm.broadcastIntent(…

 

 

可执行文件\frameworks\base\cmds\am\am定义了命令:

  base=/system

//程序的位置(./out/target/product/avl8890/system/framework/am.jar)

  export CLASSPATH=$base/framework/am.jar

  exec app_process $base/bin com.android.commands.am.Am "$@"  //程序的入口

 

  通过app_process创建执行com.android.commands.am.Am这样进程 $@传递所有参数给Am。

app_process其实也是个命令(\frameworks\base\cmds\app_process)。在app_process里面,还是一样利用JNI技术,在java ENV里面查找传给app_process的class,找到这个class后再去找main函数接口的field,然后再call这个main接口,这样就call到java里面去了。

 

 

编译:

LOCAL_PATH:= $(call my-dir)

#编译am.java成jar

include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_MODULE := am

include $(BUILD_JAVA_LIBRARY)

#编译am为可执行文件

include $(CLEAR_VARS)

LOCAL_MODULE := am

LOCAL_SRC_FILES := am

LOCAL_MODULE_CLASS := EXECUTABLES

LOCAL_MODULE_TAGS := optional

include $(BUILD_PREBUILT)

 

LOCAL_MODULE_CLASS 指定文件类型,apk文件用APPS, 并且 会检查 是否是apk文件,动态库so文件用SHARED_LIBRARIES ,bin文件用EXECUTABLES,其他文件 用ETC

对于已经编译好的二进制库,如果要用来被当作是依赖对象,那么应当将这些已经编译好的库作为单独的模块。对于这些已经编译好的库使用 BUILD_PREBUILT 或 BUILD_MULTI_PREBUILT。

Diff命令创建Patch

diff -u a.txt b.txt > diff1.txt

这是以a为原始文件,b为目标文件

使用以下指令就可以将b.txt的内容还原为a.txt的内容

patch -R b.txt < diff1.txt

exec与source

有两种方法执行shell scripts,一种是新产生一个shell,然后执行相应的shell scripts;一种是在当前shell下执行,不

再启用其他shell。

  新产生一个shell然后再执行scripts的方法是在scripts文件开头加入以下语句

  #!/bin/sh

  一般的script文件(.sh)即是这种用法。这种方法先启用新的sub-shell(新的子进程),然后在其下执行命令。

另外一种方法就是source命令,不再产生新的shell,而在当前shell下执行一切命令。source命令即点(.)命令。

系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变(fork()的子进程pid会变)。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。

BIOS/UEFI/secure boot

BIOS:"Basic Input Output System"的缩略语

 

UEFI全称统一的可扩展固件接口”(Unified Extensible Firmware Interface). 这种接口用于操作系统自动从预启动的操作环境,加载到一种操作系统上,从而使开机程序化繁为简,节省时间.

 

Secure Boot是UEFI的子规格,目的是防止恶意软件侵入,它的做法就是采用密钥。主板出

厂的时候,可以内置一些可靠的公钥。然后,任何想要在这块主板上加载的操作系统或者

硬件驱动程序,都必须通过这些公钥的认证。也就是说,这些软件必须用对应的私钥签署

过,否则主板拒绝加载。由于恶意软件不可能通过认证,因此就没有办法感染

Boot。

内核空间/用户空间

用户空间和内核空间置于这种非对称访问机制下有很好的安全性,能有效抵御恶意用户的窥探,也能防止质量低劣的用户程序的侵害,从而使系统运行得更稳定可靠。

用户空间与内核空间的权限不同,内核空间拥有所有硬件设备的权限,用户空间只有普通硬件的权限。

Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟地址空间也为0~4G.Linux内核将这4G字节的空间分为两部分。将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为"内核空间".而将较低的3G字节(从虚拟地址 0x00000000到0xBFFFFFFF),供各个进程使用,称为"用户空间)。因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。

内核空间和用户空间一般通过系统调用、ioctl、sysfs、proc等来进行通信。一般的硬件体系机构都提供一种“门”机制。“门”的含义是指在发生了特定事件的时候低特权的应用程序可以通过这些“门”进入高特权的内核空间。我们可以形象地描述这种机制:作为一个游客,你可以买票要求进入野生动物园,但你必须老老实实的坐在观光车上,按照规定的路线观光游览。

出于效率和代码大小的考虑,内核程序不能使用标准库函数(当然还有其它的顾虑,详细原因请查阅参考资料2)因此内核开发不如用户程序开发那么方便。

现在,越来越多的应用程序需要编写内核级和用户级的程序来一起完成具体的任务,通常采用以下模式:首先,编写内核服务程序利用内核空间提供的权限和服务来接收、处理和缓存数据;然后编写用户程序来和先前完成的内核服务程序交互

寄存器

堆栈指针r13(SP):每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。

连接寄存器r14(LR):每种模式下r14都有自身版组,它有两个特殊功能。

1,保存子程序返回地址。

2,当异常发生时,异常模式的r14用来保存异常返回地址,将r14如栈可以处理嵌套中断。

程序计数器r15(PC)

posted on 2016-12-14 12:12  月下银狼  阅读(489)  评论(0编辑  收藏  举报

导航