张帅依的博客

积累点滴.

DexClassLoader动态加载

Android动态加载jar/dex
Android中的动态加载机制
示例代码

1. 准备dex文件

1.1 编写

接口:

package com.dex.test;

public interface IDextest {
    public String getDexString();
}

实现:

package com.dex.test;

public class Dextest implements IDextest{
    @Override
    public String getDexString() {
        return "here dex test!!";
    }
}

1.2 导出jar包

导出jar包
导出时不用选择接口文件。

1.3 使用dx转换

dx在sdk/build-tools/android-4.4.2/下,执行/opt/android/sdk/build-tools/android-4.4.2/dx –dex –output=test.jar dextest.jar

Linux多线程编程

linux多线程编程

pthread_create

void *test_thread(void *arg) {
    int *num = (int *)arg;  //可以得到参数
}

pthread_t thread_id;
int testNum=1;
pthread_create(&thread_id, NULL, test_thread, (void *)&testNum);

pthread_detach与pthread_join

调用pthread_join(pthread_id)后,如果该线程没有运行结束,调用者会被阻塞;这时可以在子线程中加入代码
pthread_detach(pthread_self())
或者父线程调用
pthread_detach(thread_id)(非阻塞,可立即返回)
这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源

pthread_cond_wait

pthread_cond_wait
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使”条件成立”(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);

//等待
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex)
//激活
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
//注销
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);

环形buffer

示例代码

定义

#define BUFFER_SIZE 0xF 
typedef struct {
    uint32_t wptr;   ///< buffer存储位置,索引范围:[0:2*BUFFER_SIZE+1]
    uint32_t rptr;   ///< buffer读取位置,索引范围:[0:2*BUFFER_SIZE+1]
    uint8_t buffer[BUFFER_SIZE+1];  ///< buffer大小为BUFFER_SIZE+1
}ring_buffer_t; 

使用

若BUFFER_SIZE=3,wptr和rptr的索引为[0:7]
1. wptr=rptr时buffer为空
2. wptr和rptr之间的差值为BUFFER_SIZE+1即4时buffer为满
3. wptr和rptr的范围通过pbuf->wptr &= (BUFFER_SIZE<<1)|0x1 确定,BUFFER_SIZE的取值应该是N个2进制1??

__inline uint32_t ring_buffer_is_empty(ring_buffer_t *pbuf) {
    return (pbuf->wptr==pbuf->rptr);
}

__inline uint32_t ring_buffer_is_full(ring_buffer_t *pbuf) {
    return ((pbuf->wptr^pbuf->rptr)==(BUFFER_SIZE+1));
}

__inline void ring_buffer_flush(ring_buffer_t *pbuf) {
    pbuf->wptr = pbuf->rptr = 0;
}

void fill_ring_buffer(ring_buffer_t *pbuf, uint8_t data) {
    pbuf->buffer[pbuf->wptr&BUFFER_SIZE] = data;
    pbuf->wptr++;
    pbuf->wptr &= (BUFFER_SIZE<<1)|0x1;
}

uint8_t dump_ring_buffer(ring_buffer_t *pbuf) {
    uint8_t data;
    data = pbuf->buffer[pbuf->rptr&BUFFER_SIZE];
    pbuf->rptr++;
    pbuf->rptr &= (BUFFER_SIZE<<1)|0x1;

    return data;
}

Objdump学习

1. 简单程序hello world

#include <stdio.h>

int main(int argc, char** argv) {
    printf("hello world!!\n");
    int a = 0x123;
    int b = 0x234;
    int c = a + b;
    printf("c is: 0x%x\n", c);
    return 0;
}

编译gcc hello.c -o hello

1.1 gcc -S

gcc hello.c -S -o hello.s
查看hello.s内容cat hello.s

    .file   "hello.c"
    .section        .rodata
.LC0:
    .string "hello world!!"
.LC1:
    .string "c is: 0x%x\n"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movl    %edi, -20(%rbp)
    movq    %rsi, -32(%rbp)
    movl    $.LC0, %edi
    call    puts
    movl    $291, -4(%rbp)
    movl    $564, -8(%rbp)
    movl    -8(%rbp), %eax
    movl    -4(%rbp), %edx
    leal    (%rdx,%rax), %eax
    movl    %eax, -12(%rbp)
    movl    $.LC1, %eax
    movl    -12(%rbp), %edx
    movl    %edx, %esi
    movq    %rax, %rdi
    movl    $0, %eax
    call    printf
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.4.7-1ubuntu2) 4.4.7"
    .section        .note.GNU-stack,"",@progbits

1.2 objdump指令

1.2.1 objdump -s hello

显示所有section内容

objdump -s -j .rodata hello

hello:     file format elf64-x86-64

Contents of section .rodata:
400688 01000200 68656c6c 6f20776f 726c6421  ....hello world!
400698 21006320 69733a20 30782578 0a00      !.c is: 0x%x..  
只显示.rodata部分

1.2.2 objdump -S hello

objdump -S -j .rodata hello
hello:     file format elf64-x86-64

Disassembly of section .rodata:

0000000000400688 <_IO_stdin_used>:
400688:       01 00 02 00 68 65 6c 6c 6f 20 77 6f 72 6c 64 21     ....hello world!
400698:       21 00 63 20 69 73 3a 20 30 78 25 78 0a 00           !.c is: 0x%x..

各段含义

汇编中bss,data,text,rodata,heap,stack,意义
bss段:

BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。BSS段属于静态内存分配。

data段:

数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。       

text段:

代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等

rodata段:

存放C中的字符串和#define定义的常量

ARM汇编

参数传递

当少于四个时,按从左到右的顺序依次放在r0,r1,r2,r3中;
当多于四个时,前四个放在r0,r1,r2,r3中,剩余的放在堆栈中,
最后一个参数先入栈,第五个参数最后入栈,即从右到左入栈

返回值

结果为32位时,通过R0返回
结果为64位时,r0放低32位,r1放高32位        

ARM汇编指令集

BL

BL是arm汇编中用来调用子程序的指令,它把BL后面一条指令的地址放到R14寄存器里,R15寄存器(PC当前指针地址)就设置成要跳往的地址。这样在这个子程序返回时,再mov PC, R14就可以返回到BL后面的地址了

BEQ

BEQ指定是跳转指令,但是跳转要满足一定的条件,例:CMP R1,#0 BEQ Label 即当R1和0相等的时候程序跳到标号Label处执行。(BEQ执行后不调回去??)

LDR/STR

ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。比如想把数据从内存中某处读取到寄存器中,只能使用ldr,比如:

ldr r0, 0x12345678

就是把0x12345678这个地址中的值存放到r0中。而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。

LDR伪指令

ldr r0, =0x12345678
把0x12345678这个地址写到r0中

LDMIA

LDMIA R0! ,{R1,R2} 是指将R0指向的单元中的数据读出到R1,R2中
R1←[R0] R2←[R0+4]

BIC

位清除
BIC R0, R0, #0xF0000000 将R0高4位清零 BIC R1, R1, #0x0F 将R1低4位清0

网络抓包wireshark

抓取youku

先使用wireshark抓取了一次youku申请播放的过程

过滤字符串

在Filter里输入:http contains “getPlayList”

过滤ip

ip.src==101.227.10.18 or ip.dst==101.227.10.18

复制数据包内容

选择数据包,右键–copy

youku实际地址

http contains “getFlvPath”
结果 在vlc中打开路径可以播放:

Python网络编程

获取url数据

url = "http://www.youku.com/"
req = urllib.request.Request(url)
req.add_header('User-agent', 'Mozilla/5.0')
r = urllib.request.urlopen(req)
print(r.read().decode("UTF-8"))

保存图片

urllib.request.urlretrieve(url, fileName);  #将url内容存入文件

分析html

使用html.parser.HTMLParser分析html

Python学习

print

格式化输出,可以结合format格式化输出,end=“ ” 参数可以改变单次print的结束

a=10
b=12
print("0x{0:02x}+0x{1:x}={2}".format(a, b, a+b))
print("0x%02x+0x%x=%d" % (a, b, a+b))
输出相同:0x0a+0xc=22

%% 百分号标记
%c 字符及其ASCII码
%s 字符串
%d 有符号整数(十进制)
%u 无符号整数(十进制)
%o 无符号整数(八进制)
%x 无符号整数(十六进制)
%X 无符号整数(十六进制大写字符)
%e 浮点数字(科学计数法)
%E 浮点数字(科学计数法,用E代替e)
%f 浮点数字(用小数点符号)
%g 浮点数字(根据值的大小采用%e或%f)
%G 浮点数字(类似于%g)
%p 指针(用十六进制打印值的内存地址)
%n 存储输出字符的数量放进参数列表的下一个变量中

字典

headers = {'User-agent':'Mozilla/5.0',
       'cache-control':'no-cache',
       'accept':'*/*'}
for k, v in headers.items():
    print(k, v)

输出

User-agent Mozilla/5.0
cache-control no-cache
accept */*

chr hex ord

ord返回字符的ASCII print(ord(‘a’)) 输出97
chr返回字符 print(chr(97)) 输出a
hex返回16进制 print(hex(97)) 输出0x61

f=open('xxx.ts', 'r', encoding="ISO-8859-1")
context = f.read()
buf = [ord(i) for i in context]

字符串操作

查找

find和index,使用index未找到字符串会抛出异常,find不抛异常只是返回-1。

index1 = str.find("xx")
index2 = str.find("xxx", index1)#从第index1位置开始查找

复制

str2 = str[index1: index2]

时间

获取当前时间localtime,格式化时间strftime

import time
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
输出2014-07-24 19:13:43

文件操作

os.access可以判断文件是否存在,os.mkdir创建文件夹

if not os.access(filePath, os.R_OK):
    print("目录不存在")
    os.mkdir(filePath, mode=0o777)

Ts流

TS详解

整体描述

ts整包长度为188,前4字节为包头。

同步字节 传输错误指示 开始指示 传输优先级 PID 加扰控制 适配域控制 连续性计数器
8 1 1 1 13 2 2 4

sync_byte (同步字节):固定为0100 0111(0x47);该字节由解码器识别,使包头和有效负载可相互分离,MPEG-2解码器接收到MPEG-2 TS流时,首先检测包结构,在TS流中查找同步字节:

总是OX47,总位于TS包开始位置,固定间隔为188字节。同时满足这两个条件,可以确定同步。
如果出现一个字节为47hex(OX47),解码器将检测这个字节前后n倍188字节的位置是否也是同步字节。
如果是,则当前字节为同步字节;
否则,当前字节只是码流中偶尔出现的47hex,不是同步字节

Table ID长度为8bit

47  48  04  17  00  80  70 ...
同步字节:0x47
PID:0x804
Table ID:0x80

各表

PAT表PID:0,Table ID:0,包含PMT信息
CAT表PID:1,Table ID:1,包含CA的EMM信息
PMT表PID从PAT中获取,Table ID:2,包含音视频和CA的ECM信息
NIT表PID:0x10,Table ID:0x40、0x41,描述了各个频点、符号率和调制方式。

Git使用

在git status时显示与origin/master的比较

在git status时显示Your branch is ahead of ‘origin/master’ by 1 commit

git branch --set-upstream master  origin/master